diff options
| author | Stephen Blott | 2015-02-14 12:23:28 +0000 |
|---|---|---|
| committer | Stephen Blott | 2015-02-14 12:23:28 +0000 |
| commit | 39545307beea82cae85030ecea936a248a6d1544 (patch) | |
| tree | 13690e6ea9123a25a17ccc8104dc1721bb813b55 | |
| parent | 9bd6b7814fbee5508a4a746789d10c687a2c0c9b (diff) | |
| parent | 05f229201a05101ab4947bd436ec02d8864392f9 (diff) | |
| download | vimium-39545307beea82cae85030ecea936a248a6d1544.tar.bz2 | |
Merge branch 'grab-back-focus'
| -rw-r--r-- | background_scripts/settings.coffee | 1 | ||||
| -rw-r--r-- | content_scripts/vimium_frontend.coffee | 32 | ||||
| -rw-r--r-- | pages/options.coffee | 1 | ||||
| -rw-r--r-- | pages/options.html | 14 | ||||
| -rw-r--r-- | tests/dom_tests/chrome.coffee | 21 | ||||
| -rw-r--r-- | tests/dom_tests/dom_tests.coffee | 22 |
6 files changed, 68 insertions, 23 deletions
diff --git a/background_scripts/settings.coffee b/background_scripts/settings.coffee index f43bd4bc..3528e8a9 100644 --- a/background_scripts/settings.coffee +++ b/background_scripts/settings.coffee @@ -113,6 +113,7 @@ root.Settings = Settings = # put in an example search engine searchEngines: "w: http://www.wikipedia.org/w/index.php?title=Special:Search&search=%s wikipedia" newTabUrl: "chrome://newtab" + grabBackFocus: false settingsVersion: Utils.getCurrentVersion() diff --git a/content_scripts/vimium_frontend.coffee b/content_scripts/vimium_frontend.coffee index 315e64cd..5bad1148 100644 --- a/content_scripts/vimium_frontend.coffee +++ b/content_scripts/vimium_frontend.coffee @@ -44,7 +44,7 @@ settings = loadedValues: 0 valuesToLoad: [ "scrollStepSize", "linkHintCharacters", "linkHintNumbers", "filterLinkHints", "hideHud", "previousPatterns", "nextPatterns", "regexFindMode", "userDefinedLinkHintCss", - "helpDialog_showAdvancedCommands", "smoothScroll" ] + "helpDialog_showAdvancedCommands", "smoothScroll", "grabBackFocus" ] isLoaded: false eventListeners: {} @@ -96,6 +96,33 @@ settings = # frameId = Math.floor(Math.random()*999999999) +# If an input grabs the focus before the user has interacted with the page, then grab it back (if the +# grabBackFocus option is set). +class GrabBackFocus extends Mode + constructor: -> + super + name: "grab-back-focus" + keydown: => @alwaysContinueBubbling => @exit() + + @push + _name: "grab-back-focus-mousedown" + mousedown: => @alwaysContinueBubbling => @exit() + + activate = => + return @exit() unless settings.get "grabBackFocus" + @push + _name: "grab-back-focus-focus" + focus: (event) => @grabBackFocus event.target + # An input may already be focused. If so, grab back the focus. + @grabBackFocus document.activeElement if document.activeElement + + if settings.isLoaded then activate() else settings.addEventListener "load", activate + + grabBackFocus: (element) -> + return @continueBubbling unless DomUtils.isEditable element + element.blur() + @suppressEvent + # Only exported for tests. window.initializeModes = -> class NormalMode extends Mode @@ -114,6 +141,7 @@ window.initializeModes = -> new NormalMode new PassKeysMode new InsertMode permanent: true + new GrabBackFocus # # Complete initialization work that sould be done prior to DOMReady. @@ -179,7 +207,7 @@ window.initializeWhenEnabled = -> unless installedListeners # Key event handlers fire on window before they do on document. Prefer window for key events so the page # can't set handlers to grab the keys before us. - for type in ["keydown", "keypress", "keyup", "click", "focus", "blur"] + for type in [ "keydown", "keypress", "keyup", "click", "focus", "blur", "mousedown" ] do (type) -> installListener window, type, (event) -> handlerStack.bubbleEvent type, event installListener document, "DOMActivate", (event) -> handlerStack.bubbleEvent 'DOMActivate', event installedListeners = true diff --git a/pages/options.coffee b/pages/options.coffee index 93c9b503..d2950348 100644 --- a/pages/options.coffee +++ b/pages/options.coffee @@ -257,6 +257,7 @@ initOptionsPage = -> regexFindMode: CheckBoxOption scrollStepSize: NumberOption smoothScroll: CheckBoxOption + grabBackFocus: CheckBoxOption searchEngines: TextOption searchUrl: NonEmptyTextOption userDefinedLinkHintCss: TextOption diff --git a/pages/options.html b/pages/options.html index d37646c4..889d5ea0 100644 --- a/pages/options.html +++ b/pages/options.html @@ -133,6 +133,20 @@ b: http://b.com/?q=%s description <td verticalAlign="top" class="booleanOption"> <div class="help"> <div class="example"> + Prevent pages from focusing an input on load (e.g. Google, Bing, etc.). + </div> + </div> + <label> + <input id="grabBackFocus" type="checkbox"/> + Don't let pages steal the focus on load + </label> + </td> + </tr> + <tr> + <td class="caption"></td> + <td verticalAlign="top" class="booleanOption"> + <div class="help"> + <div class="example"> When enabled, the HUD will not be displayed. </div> </div> diff --git a/tests/dom_tests/chrome.coffee b/tests/dom_tests/chrome.coffee index 2e7c6a5a..d6c03fc1 100644 --- a/tests/dom_tests/chrome.coffee +++ b/tests/dom_tests/chrome.coffee @@ -7,26 +7,23 @@ root.chromeMessages = [] document.hasFocus = -> true -root.chrome = { - runtime: { - connect: -> { - onMessage: { +root.chrome = + runtime: + connect: -> + onMessage: addListener: -> - } - onDisconnect: { + onDisconnect: addListener: -> - } postMessage: -> - } - onMessage: { + onMessage: addListener: -> - } sendMessage: (message) -> chromeMessages.unshift message getManifest: -> getURL: (url) -> "../../#{url}" - } storage: local: get: -> set: -> -} + sync: + get: -> + set: -> diff --git a/tests/dom_tests/dom_tests.coffee b/tests/dom_tests/dom_tests.coffee index 11fbe11f..a1ca8723 100644 --- a/tests/dom_tests/dom_tests.coffee +++ b/tests/dom_tests/dom_tests.coffee @@ -354,24 +354,24 @@ context "Triggering insert mode", document.getElementById("test-div").innerHTML = "" should "trigger insert mode on focus of text input", -> - assert.isTrue Mode.top().name == "insert" and not Mode.top().isActive() + assert.isFalse InsertMode.permanentInstance.isActive() document.getElementById("first").focus() - assert.isTrue Mode.top().name == "insert" and Mode.top().isActive() + assert.isTrue InsertMode.permanentInstance.isActive() should "trigger insert mode on focus of password input", -> - assert.isTrue Mode.top().name == "insert" and not Mode.top().isActive() + assert.isFalse InsertMode.permanentInstance.isActive() document.getElementById("third").focus() - assert.isTrue Mode.top().name == "insert" and Mode.top().isActive() + assert.isTrue InsertMode.permanentInstance.isActive() should "trigger insert mode on focus of contentEditable elements", -> - assert.isTrue Mode.top().name == "insert" and not Mode.top().isActive() + assert.isFalse InsertMode.permanentInstance.isActive() document.getElementById("fourth").focus() - assert.isTrue Mode.top().name == "insert" and Mode.top().isActive() + assert.isTrue InsertMode.permanentInstance.isActive() should "not trigger insert mode on other elements", -> - assert.isTrue Mode.top().name == "insert" and not Mode.top().isActive() + assert.isFalse InsertMode.permanentInstance.isActive() document.getElementById("fifth").focus() - assert.isTrue Mode.top().name == "insert" and not Mode.top().isActive() + assert.isFalse InsertMode.permanentInstance.isActive() context "Mode utilities", setup -> @@ -454,6 +454,10 @@ context "PostFindMode", testContent = "<input type='text' id='first'/>" document.getElementById("test-div").innerHTML = testContent document.getElementById("first").focus() + # For these tests, we need to push GrabBackFocus out of the way. When it exits, it updates the badge, + # which interferes with event suppression within insert mode. This cannot happen in normal operation, + # because GrabBackFocus exits on the first keydown. + Mode.top().exit() @postFindMode = new PostFindMode tearDown -> @@ -466,7 +470,7 @@ context "PostFindMode", should "suppress unmapped printable keys", -> sendKeyboardEvent "m" - assert.equal pageKeyboardEventCount, 0 + assert.equal 0, pageKeyboardEventCount should "be deactivated on click events", -> handlerStack.bubbleEvent "click", target: document.activeElement |
