tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit 3a04ff1cc8bb61dd33224cd30b6512bda28c5d83
parent 6c4047cbb453260868cf6879dbd50cbf0bb871eb
Author: Jeremy Swinarton <jswinarton@mozilla.com>
Date:   Mon, 10 Nov 2025 15:15:28 +0000

Bug 1980036: Suppress TGHP/THP panel activation logic if already open, and improve zero delay reset logic r=sthompson,tabbrowser-reviewers

Differential Revision: https://phabricator.services.mozilla.com/D271393

Diffstat:
Mbrowser/components/tabbrowser/content/tab-hover-preview.mjs | 48++++++++++++++++++++++++++----------------------
Mbrowser/components/tabbrowser/test/browser/tabs/browser_tab_preview.js | 10+++++++---
2 files changed, 33 insertions(+), 25 deletions(-)

diff --git a/browser/components/tabbrowser/content/tab-hover-preview.mjs b/browser/components/tabbrowser/content/tab-hover-preview.mjs @@ -228,6 +228,7 @@ class TabPanel extends Panel { } activate(tab) { + let originalTab = this.#tab; this.#tab = tab; // Calling `moveToAnchor` in advance of the call to `openPopup` ensures @@ -239,6 +240,9 @@ class TabPanel extends Panel { // If the popup is closed this call will be ignored. this.#movePanel(); + originalTab?.removeEventListener("TabAttrModified", this); + this.#tab.addEventListener("TabAttrModified", this); + this.#thumbnailElement = null; this.#maybeRequestThumbnail(); if ( @@ -246,16 +250,16 @@ class TabPanel extends Panel { this.panelElement.state == "showing" ) { this.#updatePreview(); + } else { + this.#panelSet.panelOpener.execute(() => { + if (!this.#panelSet.shouldActivate()) { + return; + } + this.panelElement.openPopup(this.#tab, this.popupOptions); + }, this); + this.win.addEventListener("TabSelect", this); + this.panelElement.addEventListener("popupshowing", this); } - this.#panelSet.panelOpener.execute(() => { - if (!this.#panelSet.shouldActivate()) { - return; - } - this.panelElement.openPopup(this.#tab, this.popupOptions); - }, this); - this.win.addEventListener("TabSelect", this); - this.panelElement.addEventListener("popupshowing", this); - this.#tab.addEventListener("TabAttrModified", this); } deactivate(leavingTab = null) { @@ -501,13 +505,16 @@ class TabGroupPanel extends Panel { this.#group = group; this.#movePanel(); this.#updatePanelContent(); + Glean.tabgroup.groupInteractions.hover_preview.add(); - this.#panelSet.panelOpener.execute(() => { - if (!this.#panelSet.shouldActivate() || !this.#group.collapsed) { - return; - } - this.#doOpenPanel(); - }, this); + if (this.panelElement.state == "closed") { + this.#panelSet.panelOpener.execute(() => { + if (!this.#panelSet.shouldActivate() || !this.#group.collapsed) { + return; + } + this.#doOpenPanel(); + }, this); + } } /** @@ -576,8 +583,6 @@ class TabGroupPanel extends Panel { } this.panelElement.openPopup(this.#popupTarget, this.popupOptions); - - Glean.tabgroup.groupInteractions.hover_preview.add(); } #updatePanelContent() { @@ -698,7 +703,7 @@ class TabPreviewPanelTimedFunction { /** @type {number | null} */ #timer; - /** @type {boolean} */ + /** @type {number | null} */ #useZeroDelay; /** @type {function(): void | null} */ @@ -795,13 +800,12 @@ class TabPreviewPanelTimedFunction { */ setZeroDelay() { if (this.#useZeroDelay) { - return; + this.#win.clearTimeout(this.#useZeroDelay); } - this.#win.setTimeout(() => { - this.#useZeroDelay = false; + this.#useZeroDelay = this.#win.setTimeout(() => { + this.#useZeroDelay = null; }, this.#zeroDelayTime); - this.#useZeroDelay = true; } get delayActive() { diff --git a/browser/components/tabbrowser/test/browser/tabs/browser_tab_preview.js b/browser/components/tabbrowser/test/browser/tabs/browser_tab_preview.js @@ -1059,7 +1059,10 @@ add_task(async function delayTests() { */ add_task(async function zeroDelayTests() { await SpecialPowers.pushPrefEnv({ - set: [["ui.tooltip.delay_ms", 1000]], + set: [ + ["ui.tooltip.delay_ms", 1000], + ["ui.prefersReducedMotion", 1], + ], }); const tabUrl = @@ -1074,12 +1077,13 @@ add_task(async function zeroDelayTests() { resolved = true; }); // eslint-disable-next-line mozilla/no-arbitrary-setTimeout - let timeoutPromise = new Promise(resolve => setTimeout(resolve, 300)); + let timeoutPromise = new Promise(resolve => setTimeout(resolve, 900)); await Promise.race([openPreviewPromise, timeoutPromise]); - Assert.ok(resolved, "Zero delay is set immediately after leaving tab strip"); + Assert.ok(resolved, "Panel was opened the second time without a delay"); await closeTabPreviews(); + BrowserTestUtils.removeTab(tab); await SpecialPowers.popPrefEnv(); await resetState();