Loading browser/base/content/test/tabs/browser_tab_manager_close.js +41 −4 Original line number Original line Diff line number Diff line Loading @@ -9,14 +9,16 @@ const URL3 = "data:text/plain,tab3"; const URL4 = "data:text/plain,tab4"; const URL4 = "data:text/plain,tab4"; const URL5 = "data:text/plain,tab5"; const URL5 = "data:text/plain,tab5"; /** add_setup(async function () { * Tests that middle-clicking on a tab in the Tab Manager will close it. */ add_task(async function test_tab_manager_close() { await SpecialPowers.pushPrefEnv({ await SpecialPowers.pushPrefEnv({ set: [["browser.tabs.tabmanager.enabled", true]], set: [["browser.tabs.tabmanager.enabled", true]], }); }); }); /** * Tests that middle-clicking on a tab in the Tab Manager will close it. */ add_task(async function test_tab_manager_close_middle_click() { let win = let win = await BrowserTestUtils.openNewWindowWithFlushedCacheForMozSupports(); await BrowserTestUtils.openNewWindowWithFlushedCacheForMozSupports(); win.gTabsPanel.init(); win.gTabsPanel.init(); Loading Loading @@ -45,3 +47,38 @@ add_task(async function test_tab_manager_close() { } } await BrowserTestUtils.closeWindow(win); await BrowserTestUtils.closeWindow(win); }); }); /** * Tests that clicking the close button next to a tab manager item * will close it. */ add_task(async function test_tab_manager_close_button() { let win = await BrowserTestUtils.openNewWindowWithFlushedCacheForMozSupports(); win.gTabsPanel.init(); await addTabTo(win.gBrowser, URL1); await addTabTo(win.gBrowser, URL2); await addTabTo(win.gBrowser, URL3); await addTabTo(win.gBrowser, URL4); await addTabTo(win.gBrowser, URL5); let button = win.document.getElementById("alltabs-button"); let allTabsView = win.document.getElementById("allTabsMenu-allTabsView"); let allTabsPopupShownPromise = BrowserTestUtils.waitForEvent( allTabsView, "ViewShown" ); button.click(); await allTabsPopupShownPromise; let list = win.document.getElementById("allTabsMenu-allTabsView-tabs"); while (win.gBrowser.tabs.length > 1) { let row = list.lastElementChild; let tabClosing = BrowserTestUtils.waitForTabClosing(row.tab); let closeButton = row.lastElementChild; EventUtils.synthesizeMouseAtCenter(closeButton, { button: 1 }, win); await tabClosing; Assert.ok(true, "Closed a tab with the close button."); } await BrowserTestUtils.closeWindow(win); }); browser/modules/TabsList.jsm +26 −12 Original line number Original line Diff line number Diff line Loading @@ -258,10 +258,14 @@ class TabsPanel extends TabsListBase { } } break; break; case "command": case "command": if (event.target.hasAttribute("toggle-mute")) { if (event.target.classList.contains("all-tabs-mute-button")) { event.target.tab.toggleMuteAudio(); event.target.tab.toggleMuteAudio(); break; break; } } if (event.target.classList.contains("all-tabs-close-button")) { this.gBrowser.removeTab(event.target.tab); break; } // fall through // fall through default: default: super.handleEvent(event); super.handleEvent(event); Loading Loading @@ -317,15 +321,26 @@ class TabsPanel extends TabsListBase { row.appendChild(button); row.appendChild(button); let secondaryButton = doc.createXULElement("toolbarbutton"); let muteButton = doc.createXULElement("toolbarbutton"); secondaryButton.setAttribute( muteButton.classList.add( "class", "all-tabs-mute-button", "all-tabs-secondary-button subviewbutton subviewbutton-iconic" "all-tabs-secondary-button", "subviewbutton", "subviewbutton-iconic" ); muteButton.setAttribute("closemenu", "none"); muteButton.tab = tab; row.appendChild(muteButton); let closeButton = doc.createXULElement("toolbarbutton"); closeButton.classList.add( "all-tabs-close-button", "all-tabs-secondary-button", "subviewbutton" ); ); secondaryButton.setAttribute("closemenu", "none"); closeButton.setAttribute("closemenu", "none"); secondaryButton.setAttribute("toggle-mute", "true"); closeButton.tab = tab; secondaryButton.tab = tab; row.appendChild(closeButton); row.appendChild(secondaryButton); this._setRowAttributes(row, tab); this._setRowAttributes(row, tab); Loading @@ -346,11 +361,10 @@ class TabsPanel extends TabsListBase { this._setImageAttributes(row, tab); this._setImageAttributes(row, tab); let secondaryButton = row.querySelector(".all-tabs-secondary-button"); let muteButton = row.querySelector(".all-tabs-mute-button"); setAttributes(secondaryButton, { setAttributes(muteButton, { muted: tab.muted, muted: tab.muted, soundplaying: tab.soundPlaying, soundplaying: tab.soundPlaying, pictureinpicture: tab.pictureinpicture, hidden: !(tab.muted || tab.soundPlaying), hidden: !(tab.muted || tab.soundPlaying), }); }); } } Loading browser/themes/shared/tabs.css +23 −16 Original line number Original line Diff line number Diff line Loading @@ -752,22 +752,20 @@ toolbar:not(#TabsToolbar) #firefox-view-button:-moz-locale-dir(rtl) { border-radius: var(--arrowpanel-menuitem-border-radius); border-radius: var(--arrowpanel-menuitem-border-radius); } } .all-tabs-item:hover { background-color: var(--panel-item-hover-bgcolor); } .all-tabs-item:hover:active { background-color: var(--panel-item-active-bgcolor); } .all-tabs-item[selected] { .all-tabs-item[selected] { font-weight: bold; font-weight: bold; } } .all-tabs-item > toolbarbutton { .all-tabs-item > toolbarbutton { margin: 0; margin: 0; /* Since the background is set on the item, don't set it on the children. */ } background-color: transparent !important; .all-tabs-item > toolbarbutton:hover { background-color: var(--panel-item-hover-bgcolor); } .all-tabs-item > toolbarbutton:hover:active { background-color: var(--panel-item-active-bgcolor); } } .all-tabs-button { .all-tabs-button { Loading @@ -780,18 +778,27 @@ toolbar:not(#TabsToolbar) #firefox-view-button:-moz-locale-dir(rtl) { fill: currentColor; fill: currentColor; } } .all-tabs-secondary-button[soundplaying] { .all-tabs-secondary-button > label { display: none !important; /* override panelUI-shared.css */ } .all-tabs-secondary-button:hover { opacity: 1; } .all-tabs-mute-button[soundplaying] { list-style-image: url(chrome://global/skin/media/audio.svg); list-style-image: url(chrome://global/skin/media/audio.svg); } } .all-tabs-secondary-button[muted] { .all-tabs-mute-button[muted] { list-style-image: url(chrome://global/skin/media/audio-muted.svg); list-style-image: url(chrome://global/skin/media/audio-muted.svg); } } .all-tabs-secondary-button:hover { .all-tabs-close-button { opacity: 1; list-style-image: url(chrome://global/skin/icons/close-12.svg); } } .all-tabs-secondary-button > label { .all-tabs-close-button > .toolbarbutton-icon { display: none !important; /* override panelUI-shared.css */ width: 12px; margin-inline: 2px !important; /* override panelUI-shared.css */ } } Loading
browser/base/content/test/tabs/browser_tab_manager_close.js +41 −4 Original line number Original line Diff line number Diff line Loading @@ -9,14 +9,16 @@ const URL3 = "data:text/plain,tab3"; const URL4 = "data:text/plain,tab4"; const URL4 = "data:text/plain,tab4"; const URL5 = "data:text/plain,tab5"; const URL5 = "data:text/plain,tab5"; /** add_setup(async function () { * Tests that middle-clicking on a tab in the Tab Manager will close it. */ add_task(async function test_tab_manager_close() { await SpecialPowers.pushPrefEnv({ await SpecialPowers.pushPrefEnv({ set: [["browser.tabs.tabmanager.enabled", true]], set: [["browser.tabs.tabmanager.enabled", true]], }); }); }); /** * Tests that middle-clicking on a tab in the Tab Manager will close it. */ add_task(async function test_tab_manager_close_middle_click() { let win = let win = await BrowserTestUtils.openNewWindowWithFlushedCacheForMozSupports(); await BrowserTestUtils.openNewWindowWithFlushedCacheForMozSupports(); win.gTabsPanel.init(); win.gTabsPanel.init(); Loading Loading @@ -45,3 +47,38 @@ add_task(async function test_tab_manager_close() { } } await BrowserTestUtils.closeWindow(win); await BrowserTestUtils.closeWindow(win); }); }); /** * Tests that clicking the close button next to a tab manager item * will close it. */ add_task(async function test_tab_manager_close_button() { let win = await BrowserTestUtils.openNewWindowWithFlushedCacheForMozSupports(); win.gTabsPanel.init(); await addTabTo(win.gBrowser, URL1); await addTabTo(win.gBrowser, URL2); await addTabTo(win.gBrowser, URL3); await addTabTo(win.gBrowser, URL4); await addTabTo(win.gBrowser, URL5); let button = win.document.getElementById("alltabs-button"); let allTabsView = win.document.getElementById("allTabsMenu-allTabsView"); let allTabsPopupShownPromise = BrowserTestUtils.waitForEvent( allTabsView, "ViewShown" ); button.click(); await allTabsPopupShownPromise; let list = win.document.getElementById("allTabsMenu-allTabsView-tabs"); while (win.gBrowser.tabs.length > 1) { let row = list.lastElementChild; let tabClosing = BrowserTestUtils.waitForTabClosing(row.tab); let closeButton = row.lastElementChild; EventUtils.synthesizeMouseAtCenter(closeButton, { button: 1 }, win); await tabClosing; Assert.ok(true, "Closed a tab with the close button."); } await BrowserTestUtils.closeWindow(win); });
browser/modules/TabsList.jsm +26 −12 Original line number Original line Diff line number Diff line Loading @@ -258,10 +258,14 @@ class TabsPanel extends TabsListBase { } } break; break; case "command": case "command": if (event.target.hasAttribute("toggle-mute")) { if (event.target.classList.contains("all-tabs-mute-button")) { event.target.tab.toggleMuteAudio(); event.target.tab.toggleMuteAudio(); break; break; } } if (event.target.classList.contains("all-tabs-close-button")) { this.gBrowser.removeTab(event.target.tab); break; } // fall through // fall through default: default: super.handleEvent(event); super.handleEvent(event); Loading Loading @@ -317,15 +321,26 @@ class TabsPanel extends TabsListBase { row.appendChild(button); row.appendChild(button); let secondaryButton = doc.createXULElement("toolbarbutton"); let muteButton = doc.createXULElement("toolbarbutton"); secondaryButton.setAttribute( muteButton.classList.add( "class", "all-tabs-mute-button", "all-tabs-secondary-button subviewbutton subviewbutton-iconic" "all-tabs-secondary-button", "subviewbutton", "subviewbutton-iconic" ); muteButton.setAttribute("closemenu", "none"); muteButton.tab = tab; row.appendChild(muteButton); let closeButton = doc.createXULElement("toolbarbutton"); closeButton.classList.add( "all-tabs-close-button", "all-tabs-secondary-button", "subviewbutton" ); ); secondaryButton.setAttribute("closemenu", "none"); closeButton.setAttribute("closemenu", "none"); secondaryButton.setAttribute("toggle-mute", "true"); closeButton.tab = tab; secondaryButton.tab = tab; row.appendChild(closeButton); row.appendChild(secondaryButton); this._setRowAttributes(row, tab); this._setRowAttributes(row, tab); Loading @@ -346,11 +361,10 @@ class TabsPanel extends TabsListBase { this._setImageAttributes(row, tab); this._setImageAttributes(row, tab); let secondaryButton = row.querySelector(".all-tabs-secondary-button"); let muteButton = row.querySelector(".all-tabs-mute-button"); setAttributes(secondaryButton, { setAttributes(muteButton, { muted: tab.muted, muted: tab.muted, soundplaying: tab.soundPlaying, soundplaying: tab.soundPlaying, pictureinpicture: tab.pictureinpicture, hidden: !(tab.muted || tab.soundPlaying), hidden: !(tab.muted || tab.soundPlaying), }); }); } } Loading
browser/themes/shared/tabs.css +23 −16 Original line number Original line Diff line number Diff line Loading @@ -752,22 +752,20 @@ toolbar:not(#TabsToolbar) #firefox-view-button:-moz-locale-dir(rtl) { border-radius: var(--arrowpanel-menuitem-border-radius); border-radius: var(--arrowpanel-menuitem-border-radius); } } .all-tabs-item:hover { background-color: var(--panel-item-hover-bgcolor); } .all-tabs-item:hover:active { background-color: var(--panel-item-active-bgcolor); } .all-tabs-item[selected] { .all-tabs-item[selected] { font-weight: bold; font-weight: bold; } } .all-tabs-item > toolbarbutton { .all-tabs-item > toolbarbutton { margin: 0; margin: 0; /* Since the background is set on the item, don't set it on the children. */ } background-color: transparent !important; .all-tabs-item > toolbarbutton:hover { background-color: var(--panel-item-hover-bgcolor); } .all-tabs-item > toolbarbutton:hover:active { background-color: var(--panel-item-active-bgcolor); } } .all-tabs-button { .all-tabs-button { Loading @@ -780,18 +778,27 @@ toolbar:not(#TabsToolbar) #firefox-view-button:-moz-locale-dir(rtl) { fill: currentColor; fill: currentColor; } } .all-tabs-secondary-button[soundplaying] { .all-tabs-secondary-button > label { display: none !important; /* override panelUI-shared.css */ } .all-tabs-secondary-button:hover { opacity: 1; } .all-tabs-mute-button[soundplaying] { list-style-image: url(chrome://global/skin/media/audio.svg); list-style-image: url(chrome://global/skin/media/audio.svg); } } .all-tabs-secondary-button[muted] { .all-tabs-mute-button[muted] { list-style-image: url(chrome://global/skin/media/audio-muted.svg); list-style-image: url(chrome://global/skin/media/audio-muted.svg); } } .all-tabs-secondary-button:hover { .all-tabs-close-button { opacity: 1; list-style-image: url(chrome://global/skin/icons/close-12.svg); } } .all-tabs-secondary-button > label { .all-tabs-close-button > .toolbarbutton-icon { display: none !important; /* override panelUI-shared.css */ width: 12px; margin-inline: 2px !important; /* override panelUI-shared.css */ } }