commit 18653126ab20f74f6445523e86cf9d6b0b813a67
parent f31037dc64adc9d507c0ebe2bbb6c8de82ffbde0
Author: Jonathan Sudiaman <jsudiaman@mozilla.com>
Date: Thu, 6 Nov 2025 19:02:46 +0000
Bug 1996066 - Split View: Ensure that status panel shows up on the correct side. r=tabbrowser-reviewers,desktop-theme-reviewers,nsharpley
Differential Revision: https://phabricator.services.mozilla.com/D271143
Diffstat:
5 files changed, 90 insertions(+), 10 deletions(-)
diff --git a/browser/components/tabbrowser/content/tabbrowser.js b/browser/components/tabbrowser/content/tabbrowser.js
@@ -628,7 +628,7 @@
this._tabForBrowser.set(browser, tab);
- this._appendStatusPanel();
+ this.appendStatusPanel();
// This is the initial browser, so it's usually active; the default is false
// so we have to update it:
@@ -851,8 +851,8 @@
return findBar;
}
- _appendStatusPanel() {
- this.selectedBrowser.insertAdjacentElement("afterend", StatusPanel.panel);
+ appendStatusPanel(browser = this.selectedBrowser) {
+ browser.insertAdjacentElement("afterend", StatusPanel.panel);
}
_updateTabBarForPinnedTabs() {
@@ -1401,7 +1401,7 @@
this._selectedTab = newTab;
this.showTab(newTab);
- this._appendStatusPanel();
+ this.appendStatusPanel();
this._updateVisibleNotificationBox(newBrowser);
diff --git a/browser/components/tabbrowser/test/browser/statuspanel/browser.toml b/browser/components/tabbrowser/test/browser/statuspanel/browser.toml
@@ -3,4 +3,6 @@ support-files = ["head.js"]
["browser_show_statuspanel_idn.js"]
+["browser_show_statuspanel_splitview.js"]
+
["browser_show_statuspanel_twice.js"]
diff --git a/browser/components/tabbrowser/test/browser/statuspanel/browser_show_statuspanel_splitview.js b/browser/components/tabbrowser/test/browser/statuspanel/browser_show_statuspanel_splitview.js
@@ -0,0 +1,55 @@
+/* Any copyright is dedicated to the Public Domain.
+ https://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+const TEST_URL = "https://example.com";
+
+async function addTabAndLoadBrowser() {
+ const tab = BrowserTestUtils.addTab(gBrowser, TEST_URL);
+ await BrowserTestUtils.browserLoaded(tab.linkedBrowser);
+ return tab;
+}
+
+async function showStatusPanel() {
+ window.XULBrowserWindow.overLink = TEST_URL;
+ window.StatusPanel.update();
+ return promiseStatusPanelShown(window, TEST_URL);
+}
+
+async function hideStatusPanel() {
+ window.XULBrowserWindow.overLink = "";
+ window.StatusPanel.update();
+ return promiseStatusPanelHidden(window);
+}
+
+add_task(async function test_show_statuspanel_in_split_view() {
+ const tab1 = await addTabAndLoadBrowser();
+ const tab2 = await addTabAndLoadBrowser();
+ await BrowserTestUtils.switchTab(gBrowser, tab1);
+
+ info("Activate split view.");
+ const splitView = gBrowser.addTabSplitView([tab1, tab2]);
+ const panel1 = document.getElementById(tab1.linkedPanel);
+ const panel2 = document.getElementById(tab2.linkedPanel);
+
+ info("Hover over the active panel.");
+ EventUtils.synthesizeMouseAtCenter(panel1, { type: "mousemove" });
+ await showStatusPanel();
+ Assert.ok(
+ panel1.contains(StatusPanel.panel),
+ "Hover link shown within the active panel."
+ );
+ await hideStatusPanel();
+
+ info("Hover over the inactive panel.");
+ EventUtils.synthesizeMouseAtCenter(panel2, { type: "mousemove" });
+ await showStatusPanel();
+ Assert.ok(
+ panel2.contains(StatusPanel.panel),
+ "Hover link shown within the inactive panel."
+ );
+ await hideStatusPanel();
+
+ splitView.close();
+});
diff --git a/browser/themes/shared/tabbrowser/content-area.css b/browser/themes/shared/tabbrowser/content-area.css
@@ -293,6 +293,11 @@ split-view-footer,
@media -moz-pref("browser.tabs.hideStatusPanel") {
visibility: hidden;
}
+
+ /* Ensure that this appears on top of the split view footer. */
+ .split-view-panel & {
+ z-index: 1;
+ }
}
#statuspanel-label,
diff --git a/toolkit/content/widgets/tabbox.js b/toolkit/content/widgets/tabbox.js
@@ -270,21 +270,35 @@
*/
#splitViewSplitter = null;
+ static #SPLIT_VIEW_PANEL_EVENTS = Object.freeze([
+ "click",
+ "focus",
+ "mouseover",
+ "mouseout",
+ ]);
+
constructor() {
super();
this._tabbox = null;
}
handleEvent(e) {
+ const browser = e.currentTarget;
+ const tabbrowser = browser.getTabBrowser();
switch (e.type) {
case "click":
case "focus": {
- const browser = e.currentTarget;
- const tab = browser.getTabBrowser().getTabForBrowser(browser);
+ const tab = tabbrowser.getTabForBrowser(browser);
const tabstrip = this.tabbox.tabs;
tabstrip.selectedItem = tab;
break;
}
+ case "mouseover":
+ tabbrowser.appendStatusPanel(browser);
+ break;
+ case "mouseout":
+ tabbrowser.appendStatusPanel();
+ break;
}
}
@@ -362,8 +376,10 @@
const panelEl = document.getElementById(panel);
panelEl?.classList.add("split-view-panel");
panelEl?.setAttribute("column", i);
- panelEl?.querySelector("browser")?.addEventListener("click", this);
- panelEl?.querySelector("browser")?.addEventListener("focus", this);
+ const browser = panelEl?.querySelector("browser");
+ for (const eventType of MozTabpanels.#SPLIT_VIEW_PANEL_EVENTS) {
+ browser?.addEventListener(eventType, this);
+ }
}
this.#splitViewPanels = newPanels;
this.#isSplitViewActive = !!newPanels.length;
@@ -384,8 +400,10 @@
const panelEl = document.getElementById(panel);
panelEl?.classList.remove("split-view-panel");
panelEl?.removeAttribute("column");
- panelEl?.querySelector("browser")?.removeEventListener("click", this);
- panelEl?.querySelector("browser")?.removeEventListener("focus", this);
+ const browser = panelEl?.querySelector("browser");
+ for (const eventType of MozTabpanels.#SPLIT_VIEW_PANEL_EVENTS) {
+ browser?.removeEventListener(eventType, this);
+ }
if (updateArray) {
const index = this.#splitViewPanels.indexOf(panel);
if (index !== -1) {