diff --git a/src/actors/ContextMenu.types.ts b/src/actors/ContextMenu.types.ts index b4ce07b..ef9a516 100644 --- a/src/actors/ContextMenu.types.ts +++ b/src/actors/ContextMenu.types.ts @@ -13,4 +13,5 @@ export interface ContextMenuInfo { } textSelection?: string + href?: string } diff --git a/src/actors/ContextMenuChild.ts b/src/actors/ContextMenuChild.ts index a5616f7..269498c 100644 --- a/src/actors/ContextMenuChild.ts +++ b/src/actors/ContextMenuChild.ts @@ -11,6 +11,16 @@ const lazy = lazyESModuleGetters({ }) export class ContextMenuChild extends JSWindowActorChild { + getHrefIfExists(target: Node): string | undefined { + if ((target as HTMLAnchorElement).href) { + return (target as HTMLAnchorElement).href + } + + if (target.parentElement) { + return this.getHrefIfExists(target.parentElement) + } + } + handleEvent(event: MouseEvent & { inputSource: number }) { const data: { position: ContextMenuInfo['position'] @@ -29,6 +39,8 @@ export class ContextMenuChild extends JSWindowActorChild { data.textSelection = selectionInfo.fullText } + if (event.target) data.href = this.getHrefIfExists(event.target as Node) + this.sendAsyncMessage('contextmenu', data satisfies ContextMenuInfo) } } diff --git a/src/content/browser/components/contextMenus/BrowserContextMenu.svelte b/src/content/browser/components/contextMenus/BrowserContextMenu.svelte index 385bb3a..7bac34c 100644 --- a/src/content/browser/components/contextMenus/BrowserContextMenu.svelte +++ b/src/content/browser/components/contextMenus/BrowserContextMenu.svelte @@ -3,14 +3,38 @@ - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> + {#if href} + { + const tab = openTab(resource.NetUtil.newURI(href)) + if (Services.prefs.getBoolPref('browser.tabs.newTabFocus', false)) { + queueMicrotask(() => setCurrentTab(tab)) + } + }} + /> + { + const clipboardHelper = getClipboardHelper() + if (href) clipboardHelper.copyString(href, 0) + }} + /> + {/if} {#if textSelection} { - const newTab = new Tab(uri) selectedTab.set(newTab.getId()) return [...tabs, newTab] }) + return newTab } export function closeTab(tab: Tab) { @@ -56,6 +57,11 @@ function getCurrent(): Tab | undefined { return tabs.readOnce().find((t) => t.getId() == internalSelectedTab) } +export function setCurrentTab(tab: Tab) { + const index = tabs.readOnce().findIndex((t) => t.getId() == tab.getId()) + setCurrentTabIndex(index) +} + export function runOnCurrentTab(method: (tab: Tab) => R): R | void { const currentTab = getCurrent() if (currentTab) return method(currentTab) @@ -120,14 +126,16 @@ export const windowApi = { showContextMenu: (menuInfo: ContextMenuInfo) => { browserContextMenuInfo.set(menuInfo) - const contextMenu = document.getElementById( - 'browser_context_menu', - ) as XULMenuPopup - contextMenu.openPopupAtScreen( - menuInfo.position.screenX, - menuInfo.position.screenY, - true, - ) + queueMicrotask(() => { + const contextMenu = document.getElementById( + 'browser_context_menu', + ) as XULMenuPopup + contextMenu.openPopupAtScreen( + menuInfo.position.screenX, + menuInfo.position.screenY, + true, + ) + }) }, } diff --git a/src/prefs.js b/src/prefs.js index a64c1cf..9dd6394 100644 --- a/src/prefs.js +++ b/src/prefs.js @@ -31,6 +31,9 @@ pref('browser.keybinds.tab7', 'accel+7'); pref('browser.keybinds.tab8', 'accel+8'); pref('browser.keybinds.findInPage', 'accel+F'); +// Behaviour prefs +pref('browser.tabs.newTabFocus', false); + // ======================================================= // Gecko prefs