Skip to content

Commit ef6bfce

Browse files
committed
chore: prepare for vertical tabs sidebar, update attributes after toggleTabstrip
1 parent 6f17ec5 commit ef6bfce

File tree

11 files changed

+189
-30
lines changed

11 files changed

+189
-30
lines changed

addon/chrome/content/click/click.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,9 @@ var TabmixTabClickOptions = {
5151
return;
5252
}
5353

54-
const clickOutTabs = aEvent.target.localName == "arrowscrollbox";
55-
const tab = clickOutTabs ? gBrowser._selectedTab : aEvent.target.closest("tab.tabbrowser-tab");
54+
const targetTab = aEvent.target.closest("tab.tabbrowser-tab");
55+
const clickOutTabs = !targetTab;
56+
const tab = targetTab ?? gBrowser.selectedTab;
5657

5758
// we replace click handler from tab binding with this to make sure that we
5859
// always call onMouseCommand (if we need to) before we call tab flip.

addon/chrome/content/extensions/extensions.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -410,10 +410,11 @@ var TMP_extensionsCompatibility = {
410410
// https://addons.mozilla.org/en-US/firefox/addon/tabkit-2nd-edition/
411411
let isVertical = typeof VerticalTabs == "object" ||
412412
typeof VerticalTabsReloaded == "object" ||
413-
typeof gBrowser.tabContainer._verticalTabs == "boolean" ||
413+
!Tabmix.isVersion(1300) && typeof gBrowser.tabContainer._verticalTabs == "boolean" ||
414414
typeof sidetabs == "object" ||
415415
typeof tabkit == "object" ||
416-
typeof tabkitGlobal == "object";
416+
typeof tabkitGlobal == "object" ||
417+
Tabmix.tabsUtils.isVerticalTabs;
417418
let treeStyleTab = typeof TreeStyleTabService == "object";
418419
Tabmix.extensions.verticalTabBar = isVertical || treeStyleTab;
419420
Tabmix.extensions.verticalTabs = isVertical && !treeStyleTab;

addon/chrome/content/overlay/multirow.css

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737

3838
#tabmix-scrollbox:not([overflowing="true"]),
3939
#tabmix-scrollbox[flowing="singlebar"],
40+
#tabmix-scrollbox[verticalTabs],
4041
#tabmix-scrollbox[defaultScrollButtons] {
4142
visibility: collapse;
4243
}

addon/chrome/content/preferences/appearance.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,12 @@ var gAppearancePane = {
66
var browserWindow = Tabmix.getTopWin();
77
// disable options for position the tabbar and scroll mode if TreeStyleTab extension installed
88
if (browserWindow.Tabmix.extensions.verticalTabBar) {
9-
Tabmix.setItem("treeStyleTab.msg", "hidden", null);
9+
const description = document.getElementById("treeStyleTab.msg");
10+
Tabmix.setItem(description, "hidden", null);
11+
if (browserWindow.gBrowser.tabContainer._verticalTabs) {
12+
description.innerHTML = "These preferences are not in use for vertical tabs.";
13+
description.style.width = "25em";
14+
}
1015
Tabmix.setItem("tabBarDisplay", "tstInstalled", true);
1116
Tabmix.setItem("tabBarPosition", "disabled", true);
1217
Tabmix.setItem("tabsScroll", "disabled", true);

addon/chrome/content/tab/tab.js

Lines changed: 49 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,9 @@ var TabmixTabbar = {
158158
allTabsButton.collapsed = !Services.prefs.getBoolPref("browser.tabs.tabmanager.enabled");
159159
Tabmix.setItem("tabbrowser-tabs", "showalltabsbutton", !allTabsButton.collapsed || null);
160160
}
161-
Tabmix.setItem("TabsToolbar", "tabBarSpace", Tabmix.prefs.getBoolPref("tabBarSpace") || null);
161+
const tabBarSpace = Tabmix.prefs.getBoolPref("tabBarSpace") || null;
162+
Tabmix.setItem(tabBar.arrowScrollbox, "tabBarSpace", tabBarSpace);
163+
Tabmix.setItem("TabsToolbar", "tabBarSpace", tabBarSpace);
162164
this.setShowNewTabButtonAttr();
163165

164166
if (start)
@@ -395,6 +397,13 @@ Tabmix.tabsUtils = {
395397
return !this.getCollapsedState.collapsed;
396398
},
397399

400+
get isVerticalTabs() {
401+
return (
402+
this.tabBar.getAttribute("orient") === "vertical" &&
403+
this.tabBar.arrowScrollbox.getAttribute("orient") === "vertical"
404+
);
405+
},
406+
398407
get getCollapsedState() {
399408
const toolbar = document.getElementById("TabsToolbar");
400409
const tabBar = gBrowser.tabContainer;
@@ -416,6 +425,43 @@ Tabmix.tabsUtils = {
416425

417426
init() {
418427
TMP_eventListener.toggleEventListener(this.tabBar, this.events, true, this);
428+
if (Tabmix.isVersion(1300) && window.SidebarController.sidebarRevampEnabled) {
429+
// handle click/dblclick event on the empty space below the tabs,
430+
// clicking on this area should be tarted as a click on the tabbar
431+
// and sent to event TabmixTabClickOptions
432+
let timeoutId, observer;
433+
const addSidbarListeners = () => {
434+
const sidbarHtml = document.getElementById("sidebar-main")?.firstElementChild;
435+
const sidebar = sidbarHtml?.shadowRoot?.querySelector("button-group");
436+
if (sidebar) {
437+
if (this.tabBar._verticalTabs) {
438+
Tabmix.tabsUtils.initializeTabmixUI();
439+
}
440+
TMP_eventListener.toggleEventListener(sidebar, this.events, true, event => {
441+
const isSidebarButton = event.originalTarget.closest("button");
442+
if (this.tabBar._verticalTabs && !isSidebarButton) {
443+
this.handleEvent(event);
444+
}
445+
});
446+
clearTimeout(timeoutId);
447+
observer.disconnect();
448+
}
449+
};
450+
451+
observer = new MutationObserver(addSidbarListeners);
452+
observer.observe(document, {childList: true, subtree: true});
453+
454+
// throw an error if we can't find the sidebar after 1000ms
455+
timeoutId = setTimeout(() => {
456+
const message = `Error:\nTabmix can't find the sidebar DOM element to add click/dblclick listeners to it.
457+
\n\nTry Tabmix latest development version from https://bitbucket.org/onemen/tabmixplus-for-firefox/downloads/
458+
\nReport about this to Tabmix developer at https://github.com/onemen/TabMixPlus/issues`;
459+
console.error(message);
460+
observer.disconnect();
461+
}, 1000);
462+
463+
addSidbarListeners();
464+
}
419465

420466
if (this.initialized) {
421467
Tabmix.log("initializeTabmixUI - some extension initialize tabbrowser-tabs binding again");
@@ -505,15 +551,8 @@ Tabmix.tabsUtils = {
505551

506552
handleEvent(aEvent) {
507553
switch (aEvent.type) {
508-
case "MozMouseHittest":
509-
if (Tabmix.keyModifierDown && !document.hasFocus()) {
510-
Tabmix.keyModifierDown = false;
511-
}
512-
if (aEvent.button === 0 && (Tabmix.keyModifierDown || aEvent.detail > 0))
513-
aEvent.stopPropagation();
514-
break;
515554
case "dblclick":
516-
if (Tabmix.prefs.getBoolPref("tabbar.click_dragwindow") &&
555+
if (!this.tabBar._verticalTabs && Tabmix.prefs.getBoolPref("tabbar.click_dragwindow") &&
517556
Tabmix.prefs.getBoolPref("tabbar.dblclick_changesize") &&
518557
!TabmixSvc.isMac && aEvent.target.localName === "arrowscrollbox") {
519558
let displayAppButton = !document.getElementById("titlebar").hidden;
@@ -956,7 +995,7 @@ Tabmix.tabsUtils = {
956995
// and add the difference to #tabbrowser-arrowscrollbox margin top/bottom
957996
// with --tabmix-multirow-margin
958997
const reduceMargin = this.protonValues.enabled &&
959-
gBrowser.tabContainer.attributes.orient.value === "horizontal" &&
998+
gBrowser.tabContainer.attributes.orient?.value !== "vertical" &&
960999
TabmixTabbar.visibleRows > 1;
9611000
const margin = reduceMargin ? "1px" : "";
9621001
document.documentElement.style.setProperty(this.protonValues.name, margin);

addon/chrome/content/tabmix.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1005,8 +1005,14 @@ var TMP_eventListener = {
10051005
if ((Tabmix.isVersion(1170) ? aEvent?.inputSource : aEvent?.mozInputSource) == MouseEvent.MOZ_SOURCE_MOUSE) {
10061006
direction = direction > 0 ? 1 : -1;
10071007
tabBar.advanceSelectedTab(direction, true);
1008+
if (Tabmix.isVersion(1270) && Tabmix.tabsUtils.isVerticalTabs) {
1009+
gBrowser.selectedTab.scrollIntoView({
1010+
block: "nearest",
1011+
behavior: "smooth",
1012+
});
1013+
}
10081014
}
1009-
} else if (direction !== 0 && !Tabmix.extensions.treeStyleTab) {
1015+
} else if (direction !== 0 && !Tabmix.tabsUtils.isVerticalTabs && !Tabmix.extensions.treeStyleTab) {
10101016
// this code is based on arrowscrollbox.js on_wheel event handler
10111017
let scrollByDelta = function(delta, useInstant) {
10121018
let instant;

addon/chrome/skin/general.css

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,17 @@
3232
}
3333

3434
/* :::: Space on tab bar :::: */
35-
#TabsToolbar[tabBarSpace] #tabbrowser-arrowscrollbox {
35+
#tabbrowser-arrowscrollbox[orient="horizontal"][tabBarSpace] {
3636
-moz-margin-start: 0;
3737
-moz-margin-end: 0;
3838
-moz-padding-end: 15px;
3939
-moz-padding-start: 15px;
4040
}
4141

42+
#tabbrowser-arrowscrollbox[orient="vertical"][tabBarSpace] {
43+
padding-block: 15px;
44+
}
45+
4246
#TabsToolbar[tabBarSpace] .titlebar-spacer[type="pre-tabs"],
4347
#TabsToolbar[tabBarSpace] .titlebar-spacer[type="post-tabs"] {
4448
width: 25px;

addon/chrome/skin/tabmix-preferences.css

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -248,8 +248,8 @@ tabbox > tabs {
248248
display: none !important;
249249
}
250250

251-
groupbox[tstInstalled] label[TSTdisabled="true"] {
252-
color: GrayText;
251+
#tabBarDisplay[tstInstalled] label[TSTdisabled="true"] {
252+
opacity: 50%;
253253
}
254254

255255
/* rules to make the new option window look the same as the old one */

addon/modules/DynamicRules.jsm

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ const DynamicRules = {
4646
return;
4747
this._initialized = true;
4848

49-
this.orient = aWindow.document.getElementById("tabbrowser-tabs").attributes.orient.value;
49+
this.orient = aWindow.document.getElementById("tabbrowser-tabs").attributes.orient?.value ?? "horizontal";
5050
this.windows10 = aWindow.navigator.oscpu.startsWith("Windows NT 10.0");
5151

5252
lazy.Prefs.addObserver("", this);
@@ -77,7 +77,7 @@ const DynamicRules = {
7777
const tabsMutate = aMutations => {
7878
for (let mutation of aMutations) {
7979
if (mutation.attributeName == "orient") {
80-
this.orient = mutation.target.orient || mutation.target.attributes.orient.value;
80+
this.orient = mutation.target.orient || mutation.target.attributes.orient?.value || "horizontal";
8181
this.updateStyleType();
8282
return;
8383
}
@@ -142,24 +142,24 @@ const DynamicRules = {
142142

143143
// add more selectors to increase specificity of our rule in order to
144144
// override rules from Firefox and Waterfox
145-
let selector = '#TabsToolbar #TabsToolbar-customization-target #tabbrowser-tabs';
145+
let selector = '#tabbrowser-tabs';
146146

147147
let styleRules = {
148148
currentTab: {
149-
text: `${selector}[tabmix_currentStyle~="text"] .tabbrowser-tab${tabState.current}${tabTextRule}`,
150-
bg: `${selector}[tabmix_currentStyle~="bg"] .tabbrowser-tab${tabState.current}${backgroundRule}`
149+
text: `${selector}[tabmix_currentStyle~="text"] #tabbrowser-arrowscrollbox > .tabbrowser-tab${tabState.current}${tabTextRule}`,
150+
bg: `${selector}[tabmix_currentStyle~="bg"] #tabbrowser-arrowscrollbox > .tabbrowser-tab${tabState.current}${backgroundRule}`
151151
},
152152
unloadedTab: {
153-
text: `${selector}[tabmix_unloadedStyle~="text"] .tabbrowser-tab${tabState.unloaded}${tabTextRule}`,
154-
bg: `${selector}[tabmix_unloadedStyle~="bg"] .tabbrowser-tab${tabState.unloaded}${backgroundRule}`
153+
text: `${selector}[tabmix_unloadedStyle~="text"] #tabbrowser-arrowscrollbox > .tabbrowser-tab${tabState.unloaded}${tabTextRule}`,
154+
bg: `${selector}[tabmix_unloadedStyle~="bg"] #tabbrowser-arrowscrollbox > .tabbrowser-tab${tabState.unloaded}${backgroundRule}`
155155
},
156156
unreadTab: {
157-
text: `${selector}[tabmix_unreadStyle~="text"] .tabbrowser-tab${tabState.unread}${tabTextRule}`,
158-
bg: `${selector}[tabmix_unreadStyle~="bg"] .tabbrowser-tab${tabState.unread}${backgroundRule}`
157+
text: `${selector}[tabmix_unreadStyle~="text"] #tabbrowser-arrowscrollbox > .tabbrowser-tab${tabState.unread}${tabTextRule}`,
158+
bg: `${selector}[tabmix_unreadStyle~="bg"] #tabbrowser-arrowscrollbox > .tabbrowser-tab${tabState.unread}${backgroundRule}`
159159
},
160160
otherTab: {
161-
text: `${selector}[tabmix_otherStyle~="text"] .tabbrowser-tab${tabState.other}${tabTextRule}`,
162-
bg: `${selector}[tabmix_otherStyle~="bg"] .tabbrowser-tab${tabState.other}${backgroundRule}`
161+
text: `${selector}[tabmix_otherStyle~="text"] #tabbrowser-arrowscrollbox > .tabbrowser-tab${tabState.other}${tabTextRule}`,
162+
bg: `${selector}[tabmix_otherStyle~="bg"] #tabbrowser-arrowscrollbox > .tabbrowser-tab${tabState.other}${backgroundRule}`
163163
},
164164
};
165165

addon/modules/TabmixSvc.jsm

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,10 @@ TabmixSvc = {
270270

271271
ChromeUtils.import("chrome://tabmix-resource/content/TabRestoreQueue.jsm");
272272

273+
if (isVersion(1300)) {
274+
ChromeUtils.import("chrome://tabmix-resource/content/VerticalTabs.jsm");
275+
}
276+
273277
if (TabmixSvc.isG3Waterfox) {
274278
// Waterfox use build-in preference - browser.tabBar.position
275279
Services.prefs.clearUserPref("extensions.tabmix.tabBarPosition");

addon/modules/VerticalTabs.jsm

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
"use strict";
2+
3+
const EXPORTED_SYMBOLS = ["VerticalTabs"];
4+
5+
const Services = globalThis.Services || ChromeUtils.import("resource://gre/modules/Services.jsm").Services;
6+
7+
const lazy = {};
8+
9+
ChromeUtils.defineModuleGetter(lazy, "TabmixSvc",
10+
"chrome://tabmix-resource/content/TabmixSvc.jsm");
11+
12+
var VerticalTabs = {
13+
init() {
14+
if (this._initialized)
15+
return;
16+
this._initialized = true;
17+
18+
Services.prefs.addObserver("sidebar.revamp", this);
19+
Services.prefs.addObserver("sidebar.verticalTabs", this);
20+
Services.obs.addObserver(this, "quit-application");
21+
},
22+
23+
observe(subject, topic, data) {
24+
switch (topic) {
25+
case "nsPref:changed":
26+
this.onPrefChange(data);
27+
break;
28+
case "quit-application":
29+
this.onQuitApplication();
30+
break;
31+
}
32+
},
33+
34+
onPrefChange(data) {
35+
this._counter++;
36+
if (data !== "sidebar.verticalTabs" && data !== "sidebar.revamp") {
37+
return;
38+
}
39+
40+
const revamp = Services.prefs.getBoolPref("sidebar.revamp");
41+
const verticalTabs = Services.prefs.getBoolPref("sidebar.verticalTabs");
42+
43+
// save current pref value as a backup
44+
const pref = "extensions.tabmix.tabBarMode";
45+
const backupPref = `${pref}._backup`;
46+
if (data === "sidebar.verticalTabs" && verticalTabs) {
47+
Services.prefs.setIntPref(backupPref, Services.prefs.getIntPref(pref));
48+
}
49+
50+
// this is workaround until SidebarController.toggleTabstrip prevent it
51+
if (!revamp && verticalTabs) {
52+
// verticalTabs set without revamp - set it back to false
53+
Services.prefs.setBoolPref("sidebar.verticalTabs", false);
54+
return;
55+
}
56+
57+
if (data !== "sidebar.verticalTabs") {
58+
return;
59+
}
60+
61+
lazy.TabmixSvc.forEachBrowserWindow(window => {
62+
const {document, gBrowser, SidebarController, Tabmix, TabmixTabbar} = window;
63+
64+
const tabmixScrollBox = document.getElementById("tabmix-scrollbox");
65+
if (SidebarController?.sidebarVerticalTabsEnabled) {
66+
tabmixScrollBox.setAttribute("verticalTabs", true);
67+
} else {
68+
tabmixScrollBox.removeAttribute("verticalTabs", true);
69+
70+
const tabBar = gBrowser.tabContainer;
71+
tabBar.setAttribute("orient", "horizontal");
72+
73+
const toolbar = document.getElementById("TabsToolbar-customization-target");
74+
if (toolbar === tabBar.parentNode && tabmixScrollBox !== tabBar.nextSibling) {
75+
toolbar.insertBefore(tabBar, tabmixScrollBox);
76+
}
77+
78+
const useTabmixButtons = TabmixTabbar.scrollButtonsMode > TabmixTabbar.SCROLL_BUTTONS_LEFT_RIGHT;
79+
Tabmix.tabsUtils.updateScrollButtons(useTabmixButtons);
80+
}
81+
Tabmix.tabsUtils.initializeTabmixUI();
82+
});
83+
84+
// restore tabBar mode after we set orient back to horizontal
85+
if (!verticalTabs) {
86+
Services.prefs.setIntPref(pref, Services.prefs.getIntPref(backupPref, 1));
87+
Services.prefs.clearUserPref(backupPref);
88+
}
89+
},
90+
91+
onQuitApplication() {
92+
Services.prefs.removeObserver("sidebar.revamp", this);
93+
Services.prefs.removeObserver("sidebar.verticalTabs", this);
94+
Services.obs.removeObserver(this, "quit-application");
95+
},
96+
};
97+
98+
VerticalTabs.init();

0 commit comments

Comments
 (0)