diff -r 3f7ffb18fd55 toolkit/spatial-navigation/SpatialNavigation.js --- a/toolkit/spatial-navigation/SpatialNavigation.js Sat Sep 27 14:17:30 2008 -0700 +++ b/toolkit/spatial-navigation/SpatialNavigation.js Sun Sep 28 09:56:08 2008 -0400 @@ -78,20 +78,44 @@ var gDirectionalBias = 10; var gDirectionalBias = 10; var gRectFudge = 1; +// modifier values +const kAlt = "alt"; +const kShift = "shift"; +const kCtrl = "ctrl"; +const kNone = "none"; + function _onInputKeyPress (event, callback) { - // If it isn't an arrow key, bail. - if (event.keyCode != event.DOM_VK_LEFT && - event.keyCode != event.DOM_VK_RIGHT && - event.keyCode != event.DOM_VK_UP && - event.keyCode != event.DOM_VK_DOWN ) + // If it isn't enabled, bail. + if (!PrefObserver['enabled']) return; - + + if (event.keyCode != PrefObserver['keyCodeDown'] && + event.keyCode != PrefObserver['keyCodeRight'] && + event.keyCode != PrefObserver['keyCodeUp'] && + event.keyCode != PrefObserver['keyCodeLeft']) + return; + + // If it is not using the modifiers it should, bail. + if (!event.altKey && PrefObserver['modifierAlt']) + return; + + if (!event.shiftKey && PrefObserver['modifierShift']) + return; + + if (!event.crtlKey && PrefObserver['modifierCtrl']) + return; + + var target = event.target; + + var doc = target.ownerDocument; + + // If it is XUL content (e.g. about:config), bail. + if (!PrefObserver['xulContentEnabled'] && doc instanceof Ci.nsIDOMXULDocument) + return ; + // check to see if we are in a textarea or text input element, and if so, // ensure that we let the arrow keys work properly. - - var target = event.target; - if (target instanceof Ci.nsIDOMHTMLHtmlElement) { _focusNextUsingCmdDispatcher(event, callback); return; @@ -108,7 +132,8 @@ function _onInputKeyPress (event, callba if (target.textLength > 0) { - if (event.keyCode == event.DOM_VK_RIGHT || event.keyCode == event.DOM_VK_DOWN ) { + if (event.keyCode == PrefObserver['keyCodeRight'] || + event.keyCode == PrefObserver['keyCodeDown'] ) { // we are moving forward into the document if (target.textLength != target.selectionEnd) return; @@ -125,12 +150,12 @@ function _onInputKeyPress (event, callba // Check to see if we are in a select if (target instanceof Ci.nsIDOMHTMLSelectElement) { - if (event.keyCode == event.DOM_VK_DOWN ) { + if (event.keyCode == PrefObserver['keyCodeDown']) { if (target.selectedIndex + 1 < target.length) return; } - - if (event.keyCode == event.DOM_VK_UP) { + + if (event.keyCode == PrefObserver['keyCodeUp']) { if (target.selectedIndex > 0) return; } @@ -157,13 +182,12 @@ function _onInputKeyPress (event, callba return Ci.nsIDOMNodeFilter.FILTER_SKIP; } + var bestElementToFocus = null; var distanceToBestElement = Infinity; var focusedRect = _inflateRect(target.getBoundingClientRect(), - gRectFudge); - var doc = target.ownerDocument; - var treeWalker = doc.createTreeWalker(doc, Ci.nsIDOMNodeFilter.SHOW_ELEMENT, snavfilter, false); var nextNode; @@ -218,7 +242,7 @@ function _focusNextUsingCmdDispatcher(ev var windowMediator = Cc['@mozilla.org/appshell/window-mediator;1'].getService(Ci.nsIWindowMediator); var window = windowMediator.getMostRecentWindow("navigator:browser"); - if (event.keyCode == event.DOM_VK_RIGHT || event.keyCode == event.DOM_VK_DOWN ) { + if (event.keyCode == PrefObserver['keyCodeRight'] || event.keyCode != PrefObserver['keyCodeDown']) { window.document.commandDispatcher.advanceFocus(); } else { window.document.commandDispatcher.rewindFocus(); @@ -230,21 +254,21 @@ function _focusNextUsingCmdDispatcher(ev function _isRectInDirection(event, focusedRect, anotherRect) { - if (event.keyCode == event.DOM_VK_LEFT) { - return (anotherRect.left < focusedRect.left); - } - - if (event.keyCode == event.DOM_VK_RIGHT) { - return (anotherRect.right > focusedRect.right); - } - - if (event.keyCode == event.DOM_VK_UP) { - return (anotherRect.top < focusedRect.top); - } - - if (event.keyCode == event.DOM_VK_DOWN) { - return (anotherRect.bottom > focusedRect.bottom); - } + if (event.keyCode == PrefObserver['keyCodeLeft']) { + return (anotherRect.left < focusedRect.left); + } + + if (event.keyCode == PrefObserver['keyCodeRight']) { + return (anotherRect.right > focusedRect.right); + } + + if (event.keyCode == PrefObserver['keyCodeUp']) { + return (anotherRect.top < focusedRect.top); + } + + if (event.keyCode == PrefObserver['keyCodeDown']) { + return (anotherRect.bottom > focusedRect.bottom); + } return false; } @@ -271,9 +295,9 @@ function _spatialDistance(event, a, b) { var inlineNavigation = false; var mx, my, nx, ny; - - if (event.keyCode == event.DOM_VK_LEFT) { - + + if (event.keyCode == PrefObserver['keyCodeLeft']) { + // |---| // |---| // @@ -301,11 +325,11 @@ function _spatialDistance(event, a, b) else { mx = a.left; my = 0; - nx = b.right; - ny = 0; - } - } else if (event.keyCode == event.DOM_VK_RIGHT) { - + nx = b.right; + ny = 0; + } + } else if (event.keyCode == PrefObserver['keyCodeRight']) { + // |---| // |---| // @@ -332,11 +356,11 @@ function _spatialDistance(event, a, b) } else { mx = a.right; my = 0; - nx = b.left; - ny = 0; - } - } else if (event.keyCode == event.DOM_VK_UP) { - + nx = b.left; + ny = 0; + } + } else if (event.keyCode == PrefObserver['keyCodeUp']) { + // |---| |---| |---| // |---| |---| |---| // @@ -363,8 +387,8 @@ function _spatialDistance(event, a, b) nx = 0; ny = b.bottom; } - } else if (event.keyCode == event.DOM_VK_DOWN) { - + } else if (event.keyCode == PrefObserver['keyCodeDown']) { + // |---| // |---| // @@ -394,15 +418,15 @@ function _spatialDistance(event, a, b) } var scopedRect = _inflateRect(a, gRectFudge); - - if (event.keyCode == event.DOM_VK_LEFT || - event.keyCode == event.DOM_VK_RIGHT) { + + if (event.keyCode == PrefObserver['keyCodeLeft'] || + event.keyCode == PrefObserver['keyCodeRight']) { scopedRect.left = 0; scopedRect.right = Infinity; inlineNavigation = _containsRect(scopedRect, b); } - else if (event.keyCode == event.DOM_VK_UP || - event.keyCode == event.DOM_VK_DOWN) { + else if (event.keyCode == PrefObserver['keyCodeUp'] || + event.keyCode == PrefObserver['keyCodeDown']) { scopedRect.top = 0; scopedRect.bottom = Infinity; inlineNavigation = _containsRect(scopedRect, b); @@ -417,3 +441,115 @@ function _spatialDistance(event, a, b) return d; } +// Snav preference observer + +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); + this._branch.addObserver("", this, false); + + // set current or default pref values + this.observe(null, "nsPref:changed", "enabled"); + this.observe(null, "nsPref:changed", "xulContentEnabled"); + this.observe(null, "nsPref:changed", "keyCode.modifier"); + this.observe(null, "nsPref:changed", "keyCode.right"); + this.observe(null, "nsPref:changed", "keyCode.up"); + this.observe(null, "nsPref:changed", "keyCode.down"); + this.observe(null, "nsPref:changed", "keyCode.left"); + }, + + observe: function(aSubject, aTopic, aData) + { + if(aTopic != "nsPref:changed") + return; + + // aSubject is the nsIPrefBranch we're observing (after appropriate QI) + // aData is the name of the pref that's been changed (relative to aSubject) + switch (aData) { + case "enabled": + try { + this.enabled = this._branch.getBoolPref("enabled"); + } catch(e) { + this.enabled = false; + } + break; + case "xulContentEnabled": + try { + this.xulContentEnabled = this._branch.getBoolPref("xulContentEnabled"); + } catch(e) { + this.xulContentEnabled = false; + } + break; + + case "keyCode.modifier": + try { + this.keyCodeModifier = this._branch.getCharPref("keyCode.modifier"); + + // resetting modifiers + this.modifierAlt = false; + this.modifierShift = false; + this.modifierCtrl = false; + + if (this.keyCodeModifier != this.kNone) + { + // use are using '+' as a separator in about:config. + var mods = this.keyCodeModifier.split(/\++/); + for (var i = 0; i < mods.length; i++) { + var mod = mods[i].toLowerCase(); + if (mod == "") + continue; + else if (mod == kAlt) + this.modifierAlt = true; + else if (mod == kShift) + this.modifierShift = true; + else if (mod == kCtrl) + this.modifierCtrl = true; + else { + this.keyCodeModifier = kNone; + break; + } + } + } + } catch(e) { + this.keyCodeModifier = kAlt+"+"+kShift; + } + break; + case "keyCode.up": + try { + this.keyCodeUp = this._branch.getIntPref("keyCode.up"); + } catch(e) { + this.keyCodeUp = Ci.nsIDOMKeyEvent.DOM_VK_UP; + } + break; + case "keyCode.down": + try { + this.keyCodeDown = this._branch.getIntPref("keyCode.down"); + } catch(e) { + this.keyCodeDown = Ci.nsIDOMKeyEvent.DOM_VK_DOWN; + } + break; + case "keyCode.left": + try { + this.keyCodeLeft = this._branch.getIntPref("keyCode.left"); + } catch(e) { + this.keyCodeLeft = Ci.nsIDOMKeyEvent.DOM_VK_LEFT; + } + break; + case "keyCode.right": + try { + this.keyCodeRight = this._branch.getIntPref("keyCode.right"); + } catch(e) { + this.keyCodeRight = Ci.nsIDOMKeyEvent.DOM_VK_RIGHT; + } + break; + } + }, +} + +PrefObserver.register(); diff -r 3f7ffb18fd55 toolkit/spatial-navigation/tests/Makefile.in --- a/toolkit/spatial-navigation/tests/Makefile.in Sat Sep 27 14:17:30 2008 -0700 +++ b/toolkit/spatial-navigation/tests/Makefile.in Sun Sep 28 09:56:08 2008 -0400 @@ -48,6 +48,8 @@ MOCHI_TESTS = chrome/test_snav.xul \ chrome/test_snav_tightlinks.xul \ chrome/test_snav_disabledElement.xul \ chrome/test_snav_selects.xul \ + chrome/test_snav_prefDisabled.xul \ + chrome/test_snav_prefKeyCode.xul \ chrome/SpatialNavUtils.js \ $(NULL) diff -r 3f7ffb18fd55 toolkit/spatial-navigation/tests/chrome/SpatialNavUtils.js --- a/toolkit/spatial-navigation/tests/chrome/SpatialNavUtils.js Sat Sep 27 14:17:30 2008 -0700 +++ b/toolkit/spatial-navigation/tests/chrome/SpatialNavUtils.js Sun Sep 28 09:56:08 2008 -0400 @@ -1,5 +1,108 @@ var _moveTable; var _moveTable; var _moveTableIndex = 0; + +var _snavEnabledOld = null; +var _snavXULContentEnabledOld = null; +var _snavModOld = null ; +var _snavRightKeyOld = null; +var _snavLeftKeyOld = null; +var _snavDownKeyOld = null; +var _snavUpKeyOld = null; + +function prepareTest(prefs) { + + var prefService = Components.classes["@mozilla.org/preferences-service;1"] + .getService(Components.interfaces.nsIPrefService); + var snavBranch = prefService.getBranch("snav."); + + var i; + for (i = 0; i < prefs.length; i++) + { + switch (prefs[i][0]) + { + case "enabled": + try { + _snavEnabledOld = snavBranch.getBoolPref("enabled"); + } catch(e) { + _snavEnabledOld = false; + } + break; + case "xulContentEnabled": + try { + _snavXULContentEnabledOld = snavBranch.getBoolPref("xulContentEnabled"); + } catch(e) { + _snavXULContentEnabledOld = false; + } + break; + case "keyCode.modifier": + try { + _snavModOld = snavBranch.getCharPref("keyCode.modifier"); + } catch(e) { + _snavModOld = "alt+shift"; + } + break; + case "keyCode.right" : + try { + _snavRightKeyOld = snavBranch.getIntPref("keyCode.right"); + } catch(e) { + _snavRightKeyOld = Components.interfaces.nsIDOMKeyEvent.DOM_VK_RIGHT; + } + break; + case "keyCode.left" : + try { + _snavLeftKeyOld = snavBranch.getIntPref("keyCode.left"); + } catch(e) { + _snavLeftKeyOld = Components.interfaces.nsIDOMKeyEvent.DOM_VK_LEFT; + } + break; + case "keyCode.down" : + try { + _snavDownKeyOld = snavBranch.getIntPref("keyCode.down"); + } catch(e) { + _snavDownKeyOld = Components.interfaces.nsIDOMKeyEvent.DOM_VK_DOWN; + } + break; + case "keyCode.up" : + try { + _snavUpKeyOld = snavBranch.getIntPref("keyCode.up"); + } catch(e) { + _snavUpKeyOld = Components.interfaces.nsIDOMKeyEvent.DOM_VK_UP; + } + break; + } // switch + + if (prefs[i][1] == "bool") + snavBranch.setBoolPref(prefs[i][0], prefs[i][2]); + else if (prefs[i][1] == "int") + snavBranch.setIntPref(prefs[i][0], prefs[i][2]); + else if (prefs[i][1] == "char") + snavBranch.setCharPref(prefs[i][0], prefs[i][2]); + } // for +} + +// setting pref values back. +function completeTest() { + + var prefService = Components.classes["@mozilla.org/preferences-service;1"] + .getService(Components.interfaces.nsIPrefService); + var snavBranch = prefService.getBranch("snav."); + + if (_snavEnabledOld != null) + snavBranch.setBoolPref("enabled", _snavEnabledOld); + if (_snavXULContentEnabledOld != null) + snavBranch.setBoolPref("xulContentEnabled", _snavXULContentEnabledOld); + if (_snavModOld != null) + snavBranch.setCharPref("keyCode.modifier", _snavModOld); + if (_snavRightKeyOld != null) + snavBranch.setIntPref("keyCode.right", _snavRightKeyOld); + if (_snavUpKeyOld != null) + snavBranch.setIntPref("keyCode.up", _snavUpKeyOld); + if (_snavDownKeyOld != null) + snavBranch.setIntPref("keyCode.down", _snavDownKeyOld); + if (_snavLeftKeyOld != null) + snavBranch.setIntPref("keyCode.left", _snavLeftKeyOld); +} + function testMoves(table) { // document.addEventListener("focus", _verifyAndAdvance, true); @@ -15,6 +118,7 @@ function _nextMove() // When a table ends with "DONE", call finish. if (_moveTable[_moveTableIndex][0] == "DONE") { + completeTest (); SimpleTest.finish(); return; } diff -r 3f7ffb18fd55 toolkit/spatial-navigation/tests/chrome/test_snav.xul --- a/toolkit/spatial-navigation/tests/chrome/test_snav.xul Sat Sep 27 14:17:30 2008 -0700 +++ b/toolkit/spatial-navigation/tests/chrome/test_snav.xul Sun Sep 28 09:56:08 2008 -0400 @@ -59,8 +59,17 @@ var moveTable = [ ["DONE", "DONE"] ]; +var prefs = [ +["enabled", "bool", true], +["xulContentEnabled", "bool", true], +["keyCode.modifier", "char", "none"], +]; + function onLoad() { + prepareTest(prefs); + + // starting the test itself. var x = document.getElementById("some-content"); SpatialNavigation.init(x); diff -r 3f7ffb18fd55 toolkit/spatial-navigation/tests/chrome/test_snav_disabledElement.xul --- a/toolkit/spatial-navigation/tests/chrome/test_snav_disabledElement.xul Sat Sep 27 14:17:30 2008 -0700 +++ b/toolkit/spatial-navigation/tests/chrome/test_snav_disabledElement.xul Sun Sep 28 09:56:08 2008 -0400 @@ -32,7 +32,6 @@ https://bugzilla.mozilla.org/show_bug.cg
+ + Mozilla Bug 444801 +| test | +test | +