From 557bed71adfc4d3121e6c3bb561fe0e88bc4194a Mon Sep 17 00:00:00 2001 From: Karan Mahato <44karanmahato@gmail.com> Date: Thu, 2 Apr 2026 21:04:48 +0545 Subject: [PATCH 1/5] Add global toggle to disable/enable Vimium via keyboard shortcut --- background_scripts/main.js | 72 ++++++++++++++++++++---------- content_scripts/vimium_frontend.js | 8 +++- manifest.json | 5 +++ 3 files changed, 60 insertions(+), 25 deletions(-) diff --git a/background_scripts/main.js b/background_scripts/main.js index 7d37e6b1b..8203cb4a0 100644 --- a/background_scripts/main.js +++ b/background_scripts/main.js @@ -597,6 +597,48 @@ const HintCoordinator = { }, }; +let globallyDisabled = false; + +function getIconSet() { + if (bgUtils.isFirefox()) { + return { + "enabled": "../icons/action_enabled.svg", + "partial": "../icons/action_partial.svg", + "disabled": "../icons/action_disabled.svg", + }; + } + return { + "enabled": { + "16": "../icons/action_enabled_16.png", + "32": "../icons/action_enabled_32.png", + }, + "partial": { + "16": "../icons/action_partial_16.png", + "32": "../icons/action_partial_32.png", + }, + "disabled": { + "16": "../icons/action_disabled_16.png", + "32": "../icons/action_disabled_32.png", + }, + }; +} + +chrome.commands.onCommand.addListener(async (command) => { + if (command === "toggleGloballyDisabled") { + globallyDisabled = !globallyDisabled; + const iconSet = getIconSet(); + const whichIcon = globallyDisabled ? "disabled" : "enabled"; + const tabs = await chrome.tabs.query({}); + for (const tab of tabs) { + chrome.action.setIcon({ path: iconSet[whichIcon], tabId: tab.id }).catch(() => {}); + chrome.tabs.sendMessage(tab.id, { + handler: "toggleGloballyDisabled", + disabled: globallyDisabled, + }).catch(() => {}); + } + } +}); + const sendRequestHandlers = { runBackgroundCommand(request, sender) { return BackgroundCommands[request.registryEntry.command](request, sender); @@ -663,6 +705,11 @@ const sendRequestHandlers = { // specific frame that sent this request. const enabledState = exclusions.isEnabledForUrl(sender.tab.url); + if (globallyDisabled) { + enabledState.isEnabledForUrl = false; + enabledState.passKeys = ""; + } + const isTopFrame = sender.frameId == 0; if (isTopFrame) { let whichIcon; @@ -674,30 +721,7 @@ const sendRequestHandlers = { whichIcon = "enabled"; } - let iconSet = { - "enabled": { - "16": "../icons/action_enabled_16.png", - "32": "../icons/action_enabled_32.png", - }, - "partial": { - "16": "../icons/action_partial_16.png", - "32": "../icons/action_partial_32.png", - }, - "disabled": { - "16": "../icons/action_disabled_16.png", - "32": "../icons/action_disabled_32.png", - }, - }; - - if (bgUtils.isFirefox()) { - // Only Firefox supports SVG icons. - iconSet = { - "enabled": "../icons/action_enabled.svg", - "partial": "../icons/action_partial.svg", - "disabled": "../icons/action_disabled.svg", - }; - } - + const iconSet = getIconSet(); chrome.action.setIcon({ path: iconSet[whichIcon], tabId: sender.tab.id }); } diff --git a/content_scripts/vimium_frontend.js b/content_scripts/vimium_frontend.js index c4d5331ec..a080d4247 100644 --- a/content_scripts/vimium_frontend.js +++ b/content_scripts/vimium_frontend.js @@ -352,6 +352,10 @@ globalThis.lastFocusedInput = (function () { })(); const messageHandlers = { + toggleGloballyDisabled(request) { + isEnabledForUrl = !request.disabled; + HUD.show(isEnabledForUrl ? "Vimium enabled" : "Vimium disabled", 2000); + }, getFocusStatus(_request, _sender) { return { focused: windowIsFocused(), @@ -401,7 +405,9 @@ async function handleMessage(request, sender) { // Some request are handled elsewhere in the code base; ignore them here. const shouldHandleMessage = request.handler !== "userIsInteractingWithThePage" && (isEnabledForUrl || - ["checkEnabledAfterURLChange", "runInTopFrame"].includes(request.handler)); + ["checkEnabledAfterURLChange", "runInTopFrame", "toggleGloballyDisabled"].includes( + request.handler, + )); if (shouldHandleMessage) { const result = await messageHandlers[request.handler](request, sender); return result; diff --git a/manifest.json b/manifest.json index 783852cbb..6c383ad8a 100644 --- a/manifest.json +++ b/manifest.json @@ -94,6 +94,11 @@ // "strict_min_version": "109.0" // } // }, + "commands": { + "toggleGloballyDisabled": { + "description": "Toggle Vimium on/off" + } + }, "action": { "default_icon": { "16": "icons/action_disabled_16.png", From aa1d35e0e72c1e713154e86c9ed8ec3762353dde Mon Sep 17 00:00:00 2001 From: Karan Mahato <44karanmahato@gmail.com> Date: Thu, 2 Apr 2026 22:02:15 +0545 Subject: [PATCH 2/5] Add disabled state to popup and re-enable button --- background_scripts/main.js | 36 +++++++++++++++++++++++++----------- pages/action.css | 12 +++++++++--- pages/action.html | 5 +++++ pages/action.js | 13 +++++++++++++ 4 files changed, 52 insertions(+), 14 deletions(-) diff --git a/background_scripts/main.js b/background_scripts/main.js index 8203cb4a0..37fcb91d7 100644 --- a/background_scripts/main.js +++ b/background_scripts/main.js @@ -623,20 +623,34 @@ function getIconSet() { }; } +async function toggleGloballyDisabled() { + globallyDisabled = !globallyDisabled; + const iconSet = getIconSet(); + const whichIcon = globallyDisabled ? "disabled" : "enabled"; + const tabs = await chrome.tabs.query({}); + for (const tab of tabs) { + chrome.action.setIcon({ path: iconSet[whichIcon], tabId: tab.id }).catch(() => {}); + chrome.tabs.sendMessage(tab.id, { + handler: "toggleGloballyDisabled", + disabled: globallyDisabled, + }).catch(() => {}); + } +} + chrome.commands.onCommand.addListener(async (command) => { if (command === "toggleGloballyDisabled") { - globallyDisabled = !globallyDisabled; - const iconSet = getIconSet(); - const whichIcon = globallyDisabled ? "disabled" : "enabled"; - const tabs = await chrome.tabs.query({}); - for (const tab of tabs) { - chrome.action.setIcon({ path: iconSet[whichIcon], tabId: tab.id }).catch(() => {}); - chrome.tabs.sendMessage(tab.id, { - handler: "toggleGloballyDisabled", - disabled: globallyDisabled, - }).catch(() => {}); - } + await toggleGloballyDisabled(); + } +}); + +chrome.runtime.onMessage.addListener((request, _sender, sendResponse) => { + if (request.handler === "getGloballyDisabled") { + sendResponse({ globallyDisabled }); + } else if (request.handler === "toggleGloballyDisabled") { + toggleGloballyDisabled().then(() => sendResponse()); + return true; } + return false; }); const sendRequestHandlers = { diff --git a/pages/action.css b/pages/action.css index 145c3bb1d..370a93955 100644 --- a/pages/action.css +++ b/pages/action.css @@ -26,15 +26,21 @@ h1 { padding: var(--padding); } -#dialog-body > * { +#globally-disabled-notice { + padding: var(--padding); + padding-right: 0; + flex-grow: 1; +} + +#dialog-body > *, #globally-disabled-notice > * { margin: 10px 0; } -#dialog-body > *:first-child { +#dialog-body > *:first-child, #globally-disabled-notice > *:first-child { margin-top: 0; } -#dialog-body > *:last-child { +#dialog-body > *:last-child, #globally-disabled-notice > *:last-child { margin-bottom: 0; } diff --git a/pages/action.html b/pages/action.html index 2e1fae6cf..c15cf6a42 100644 --- a/pages/action.html +++ b/pages/action.html @@ -46,6 +46,11 @@