From f037e83763b1b62e048e1fc433d52b9564ce3ba0 Mon Sep 17 00:00:00 2001 From: Stephen Blott Date: Sat, 23 Aug 2014 11:40:25 +0100 Subject: Allow passing of keys to the underlying page. --- content_scripts/vimium_frontend.coffee | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'content_scripts') diff --git a/content_scripts/vimium_frontend.coffee b/content_scripts/vimium_frontend.coffee index 565c9e61..70cc5cbb 100644 --- a/content_scripts/vimium_frontend.coffee +++ b/content_scripts/vimium_frontend.coffee @@ -15,6 +15,8 @@ isShowingHelpDialog = false keyPort = null # Users can disable Vimium on URL patterns via the settings page. isEnabledForUrl = true +passKeys = null +keyQueue = null # The user's operating system. currentCompletionKeys = null validFirstKeys = null @@ -115,6 +117,7 @@ initializePreDomReady = -> getScrollPosition: -> scrollX: window.scrollX, scrollY: window.scrollY setScrollPosition: (request) -> setScrollPosition request.scrollX, request.scrollY executePageCommand: executePageCommand + currentKeyQueue: (request) -> keyQueue = request.keyQueue getActiveState: -> { enabled: isEnabledForUrl } disableVimium: disableVimium @@ -321,6 +324,15 @@ extend window, false +# Should this keyChar be passed to the underlying page? +# Keystrokes are *never* considered passKeys if the keyQueue is not empty. So, for example, if 't' is a +# passKey, then 'gt' and '99t' will neverthless be handled by vimium. +# TODO: This currently only works for unmodified keys (so not for '', or the like). It's not clear if +# this is a problem or not. I don't recall coming across a web page with modifier key bindings. Such +# bindings might be too likely to conflict with browser bindings. +isPassKey = ( keyChar ) -> + !keyQueue and passKeys and 0 <= passKeys.indexOf keyChar + handledKeydownEvents = [] # @@ -349,6 +361,9 @@ onKeypress = (event) -> handleKeyCharForFindMode(keyChar) DomUtils.suppressEvent(event) else if (!isInsertMode() && !findMode) + # Is this keyChar is to be passed to the underlying page? + if (isPassKey keyChar) + return undefined if (currentCompletionKeys.indexOf(keyChar) != -1) DomUtils.suppressEvent(event) @@ -431,6 +446,9 @@ onKeydown = (event) -> else if (KeyboardUtils.isEscape(event)) keyPort.postMessage({ keyChar:"", frameId:frameId }) + else if isPassKey KeyboardUtils.getKeyChar(event) + return undefined + # Added to prevent propagating this event to other listeners if it's one that'll trigger a Vimium command. # The goal is to avoid the scenario where Google Instant Search uses every keydown event to dump us # back into the search box. As a side effect, this should also prevent overriding by other sites. @@ -467,6 +485,7 @@ checkIfEnabledForUrl = -> isEnabledForUrl = response.isEnabledForUrl if (isEnabledForUrl) initializeWhenEnabled() + passKeys = response.passKeys else if (HUD.isReady()) # Quickly hide any HUD we might already be showing, e.g. if we entered insert mode on page load. HUD.hide() -- cgit v1.2.3 From 951f8839d02a8d85747d86ccd09efc0ee3a72501 Mon Sep 17 00:00:00 2001 From: Stephen Blott Date: Sat, 23 Aug 2014 15:26:03 +0100 Subject: Allow passing of keys to the underlying page (more minor code review). --- content_scripts/vimium_frontend.coffee | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'content_scripts') diff --git a/content_scripts/vimium_frontend.coffee b/content_scripts/vimium_frontend.coffee index 70cc5cbb..feebda07 100644 --- a/content_scripts/vimium_frontend.coffee +++ b/content_scripts/vimium_frontend.coffee @@ -117,6 +117,7 @@ initializePreDomReady = -> getScrollPosition: -> scrollX: window.scrollX, scrollY: window.scrollY setScrollPosition: (request) -> setScrollPosition request.scrollX, request.scrollY executePageCommand: executePageCommand + # FIXME: currentKeyQueue(), below, does not respect the frameId. Should it? currentKeyQueue: (request) -> keyQueue = request.keyQueue getActiveState: -> { enabled: isEnabledForUrl } disableVimium: disableVimium @@ -329,7 +330,7 @@ extend window, # passKey, then 'gt' and '99t' will neverthless be handled by vimium. # TODO: This currently only works for unmodified keys (so not for '', or the like). It's not clear if # this is a problem or not. I don't recall coming across a web page with modifier key bindings. Such -# bindings might be too likely to conflict with browser bindings. +# bindings might be too likely to conflict with browsers' native bindings. isPassKey = ( keyChar ) -> !keyQueue and passKeys and 0 <= passKeys.indexOf keyChar -- cgit v1.2.3 From 4dd09f77141b01d2ce99866cb52efc985f4f18a4 Mon Sep 17 00:00:00 2001 From: Stephen Blott Date: Sat, 23 Aug 2014 18:32:41 +0100 Subject: Allow passing of keys to the underlying page (fix/maintain order of exclusion list). --- content_scripts/vimium_frontend.coffee | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'content_scripts') diff --git a/content_scripts/vimium_frontend.coffee b/content_scripts/vimium_frontend.coffee index feebda07..34473e96 100644 --- a/content_scripts/vimium_frontend.coffee +++ b/content_scripts/vimium_frontend.coffee @@ -117,10 +117,9 @@ initializePreDomReady = -> getScrollPosition: -> scrollX: window.scrollX, scrollY: window.scrollY setScrollPosition: (request) -> setScrollPosition request.scrollX, request.scrollY executePageCommand: executePageCommand - # FIXME: currentKeyQueue(), below, does not respect the frameId. Should it? - currentKeyQueue: (request) -> keyQueue = request.keyQueue getActiveState: -> { enabled: isEnabledForUrl } disableVimium: disableVimium + currentKeyQueue: (request) -> keyQueue = request.keyQueue chrome.runtime.onMessage.addListener (request, sender, sendResponse) -> # in the options page, we will receive requests from both content and background scripts. ignore those -- cgit v1.2.3 From d230f3037e259f0bf8c3710f20a7403731caecc0 Mon Sep 17 00:00:00 2001 From: Stephen Blott Date: Sun, 24 Aug 2014 10:04:03 +0100 Subject: Better state management for passkeys. --- content_scripts/vimium_frontend.coffee | 56 ++++++++++++++++++---------------- 1 file changed, 29 insertions(+), 27 deletions(-) (limited to 'content_scripts') diff --git a/content_scripts/vimium_frontend.coffee b/content_scripts/vimium_frontend.coffee index 34473e96..d34ea761 100644 --- a/content_scripts/vimium_frontend.coffee +++ b/content_scripts/vimium_frontend.coffee @@ -13,7 +13,8 @@ findModeQueryHasResults = false findModeAnchorNode = null isShowingHelpDialog = false keyPort = null -# Users can disable Vimium on URL patterns via the settings page. +# Users can disable Vimium on URL patterns via the settings page. The following two variables +# (isEnabledForUrl and passKeys) control Vimium's enabled/disabled behaviour. isEnabledForUrl = true passKeys = null keyQueue = null @@ -117,43 +118,45 @@ initializePreDomReady = -> getScrollPosition: -> scrollX: window.scrollX, scrollY: window.scrollY setScrollPosition: (request) -> setScrollPosition request.scrollX, request.scrollY executePageCommand: executePageCommand - getActiveState: -> { enabled: isEnabledForUrl } - disableVimium: disableVimium + getActiveState: -> { enabled: isEnabledForUrl, passKeys: passKeys } + setState: setState currentKeyQueue: (request) -> keyQueue = request.keyQueue chrome.runtime.onMessage.addListener (request, sender, sendResponse) -> # in the options page, we will receive requests from both content and background scripts. ignore those # from the former. return if sender.tab and not sender.tab.url.startsWith 'chrome-extension://' - return unless isEnabledForUrl or request.name == 'getActiveState' + return unless isEnabledForUrl or request.name == 'getActiveState' or request.name == 'setState' sendResponse requestHandlers[request.name](request, sender) # Ensure the sendResponse callback is freed. false -# -# This is called once the background page has told us that Vimium should be enabled for the current URL. -# -initializeWhenEnabled = -> - document.addEventListener("keydown", onKeydown, true) - document.addEventListener("keypress", onKeypress, true) - document.addEventListener("keyup", onKeyup, true) - document.addEventListener("focus", onFocusCapturePhase, true) - document.addEventListener("blur", onBlurCapturePhase, true) - document.addEventListener("DOMActivate", onDOMActivate, true) - enterInsertModeIfElementIsFocused() +# Wrapper to install event listeners. Syntactic sugar. +installListener = (event, callback) -> document.addEventListener(event, callback, true) # -# Used to disable Vimium without needing to reload the page. -# This is called if the current page's url is blacklisted using the popup UI. +# This is called once the background page has told us that Vimium should be enabled for the current URL. +# We enable/disable Vimium by toggling isEnabledForUrl. The alternative, installing or uninstalling +# listeners, is error prone. It's more difficult to keep track of the state. # -disableVimium = -> - document.removeEventListener("keydown", onKeydown, true) - document.removeEventListener("keypress", onKeypress, true) - document.removeEventListener("keyup", onKeyup, true) - document.removeEventListener("focus", onFocusCapturePhase, true) - document.removeEventListener("blur", onBlurCapturePhase, true) - document.removeEventListener("DOMActivate", onDOMActivate, true) - isEnabledForUrl = false +installedListeners = false +initializeWhenEnabled = (newPassKeys=undefined) -> + isEnabledForUrl = true + passKeys = passKeys if typeof(newPassKeys) != 'undefined' + if (!installedListeners) + installListener "keydown", (event) -> if isEnabledForUrl then onKeydown(event) else true + installListener "keypress", (event) -> if isEnabledForUrl then onKeypress(event) else true + installListener "keyup", (event) -> if isEnabledForUrl then onKeyup(event) else true + installListener "focus", (event) -> if isEnabledForUrl then onFocusCapturePhase(event) else true + installListener "blur", (event) -> if isEnabledForUrl then onBlurCapturePhase(event) + installListener "DOMActivate", (event) -> if isEnabledForUrl then onDOMActivate(event) + enterInsertModeIfElementIsFocused() + installedListeners = true + +setState = (request) -> + isEnabledForUrl = request.enabled + passKeys = request.passKeys + initializeWhenEnabled(passKeys) if isEnabledForUrl and !installedListeners # # The backend needs to know which frame has focus. @@ -484,8 +487,7 @@ checkIfEnabledForUrl = -> chrome.runtime.sendMessage { handler: "isEnabledForUrl", url: url }, (response) -> isEnabledForUrl = response.isEnabledForUrl if (isEnabledForUrl) - initializeWhenEnabled() - passKeys = response.passKeys + initializeWhenEnabled(response.passKeys) else if (HUD.isReady()) # Quickly hide any HUD we might already be showing, e.g. if we entered insert mode on page load. HUD.hide() -- cgit v1.2.3 From d57748f902d9647c3dcf2e3c4d60411766c1bd25 Mon Sep 17 00:00:00 2001 From: Stephen Blott Date: Sun, 24 Aug 2014 11:49:01 +0100 Subject: Do not call handlers which do not exist. --- content_scripts/vimium_frontend.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'content_scripts') diff --git a/content_scripts/vimium_frontend.coffee b/content_scripts/vimium_frontend.coffee index d34ea761..3543f69c 100644 --- a/content_scripts/vimium_frontend.coffee +++ b/content_scripts/vimium_frontend.coffee @@ -127,7 +127,7 @@ initializePreDomReady = -> # from the former. return if sender.tab and not sender.tab.url.startsWith 'chrome-extension://' return unless isEnabledForUrl or request.name == 'getActiveState' or request.name == 'setState' - sendResponse requestHandlers[request.name](request, sender) + sendResponse(if requestHandlers[request.name] then requestHandlers[request.name](request, sender) else undefined) # Ensure the sendResponse callback is freed. false -- cgit v1.2.3 From 700d35a1c4ef85f97f3176aa87807f9a586bf441 Mon Sep 17 00:00:00 2001 From: Stephen Blott Date: Sun, 24 Aug 2014 12:03:41 +0100 Subject: Do not call handlers which do not exist (fixed). --- content_scripts/vimium_frontend.coffee | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'content_scripts') diff --git a/content_scripts/vimium_frontend.coffee b/content_scripts/vimium_frontend.coffee index 3543f69c..5731838c 100644 --- a/content_scripts/vimium_frontend.coffee +++ b/content_scripts/vimium_frontend.coffee @@ -127,8 +127,9 @@ initializePreDomReady = -> # from the former. return if sender.tab and not sender.tab.url.startsWith 'chrome-extension://' return unless isEnabledForUrl or request.name == 'getActiveState' or request.name == 'setState' - sendResponse(if requestHandlers[request.name] then requestHandlers[request.name](request, sender) else undefined) - # Ensure the sendResponse callback is freed. + # registerFrame requests are delivered here, but there's no handler. + return if request.handler == "registerFrame" + requestHandlers[request.name](request, sender) false # Wrapper to install event listeners. Syntactic sugar. -- cgit v1.2.3 From 5cdeb4d4ac2bc3171b47043f0275d0f8331486a6 Mon Sep 17 00:00:00 2001 From: Stephen Blott Date: Sun, 24 Aug 2014 12:10:28 +0100 Subject: Do not call handlers which do not exist (fixed, again). --- content_scripts/vimium_frontend.coffee | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'content_scripts') diff --git a/content_scripts/vimium_frontend.coffee b/content_scripts/vimium_frontend.coffee index 5731838c..2bdd85a8 100644 --- a/content_scripts/vimium_frontend.coffee +++ b/content_scripts/vimium_frontend.coffee @@ -123,12 +123,13 @@ initializePreDomReady = -> currentKeyQueue: (request) -> keyQueue = request.keyQueue chrome.runtime.onMessage.addListener (request, sender, sendResponse) -> - # in the options page, we will receive requests from both content and background scripts. ignore those + # In the options page, we will receive requests from both content and background scripts. ignore those # from the former. + console.log request.name, request return if sender.tab and not sender.tab.url.startsWith 'chrome-extension://' return unless isEnabledForUrl or request.name == 'getActiveState' or request.name == 'setState' - # registerFrame requests are delivered here, but there's no handler. - return if request.handler == "registerFrame" + # These requests are delivered to the options page, but there are no handlers there. + return if request.handler == "registerFrame" or request.handler == "frameFocused" requestHandlers[request.name](request, sender) false -- cgit v1.2.3 From b599492ea27c8c6bab38e87ef343968f5fcf58e7 Mon Sep 17 00:00:00 2001 From: Stephen Blott Date: Sun, 24 Aug 2014 17:05:05 +0100 Subject: Fix passKeys bug introduced in commit 700d35a --- content_scripts/vimium_frontend.coffee | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'content_scripts') diff --git a/content_scripts/vimium_frontend.coffee b/content_scripts/vimium_frontend.coffee index 2bdd85a8..137b9d1a 100644 --- a/content_scripts/vimium_frontend.coffee +++ b/content_scripts/vimium_frontend.coffee @@ -125,12 +125,11 @@ initializePreDomReady = -> chrome.runtime.onMessage.addListener (request, sender, sendResponse) -> # In the options page, we will receive requests from both content and background scripts. ignore those # from the former. - console.log request.name, request return if sender.tab and not sender.tab.url.startsWith 'chrome-extension://' return unless isEnabledForUrl or request.name == 'getActiveState' or request.name == 'setState' # These requests are delivered to the options page, but there are no handlers there. return if request.handler == "registerFrame" or request.handler == "frameFocused" - requestHandlers[request.name](request, sender) + sendResponse requestHandlers[request.name](request, sender) false # Wrapper to install event listeners. Syntactic sugar. -- cgit v1.2.3