Skip to content

Commit e2bcc4d

Browse files
author
Benjamin Pasero
authored
tabs - add setting to switch tabs with mouse-wheel (microsoft#13902) (microsoft#95222)
1 parent 7ddda59 commit e2bcc4d

6 files changed

Lines changed: 52 additions & 5 deletions

File tree

src/vs/base/browser/dom.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -822,6 +822,7 @@ export const EventType = {
822822
MOUSE_OUT: 'mouseout',
823823
MOUSE_ENTER: 'mouseenter',
824824
MOUSE_LEAVE: 'mouseleave',
825+
MOUSE_WHEEL: browser.isEdge ? 'mousewheel' : 'wheel',
825826
POINTER_UP: 'pointerup',
826827
POINTER_DOWN: 'pointerdown',
827828
POINTER_MOVE: 'pointermove',

src/vs/base/browser/ui/scrollbar/scrollableElement.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
*--------------------------------------------------------------------------------------------*/
55

66
import 'vs/css!./media/scrollbars';
7-
import { isEdge } from 'vs/base/browser/browser';
87
import * as dom from 'vs/base/browser/dom';
98
import { FastDomNode, createFastDomNode } from 'vs/base/browser/fastDomNode';
109
import { IMouseEvent, StandardWheelEvent, IMouseWheelEvent } from 'vs/base/browser/mouseEvent';
@@ -336,7 +335,7 @@ export abstract class AbstractScrollableElement extends Widget {
336335
this._onMouseWheel(new StandardWheelEvent(browserEvent));
337336
};
338337

339-
this._mouseWheelToDispose.push(dom.addDisposableListener(this._listenOnDomNode, isEdge ? 'mousewheel' : 'wheel', onMouseWheel, { passive: false }));
338+
this._mouseWheelToDispose.push(dom.addDisposableListener(this._listenOnDomNode, dom.EventType.MOUSE_WHEEL, onMouseWheel, { passive: false }));
340339
}
341340
}
342341

src/vs/editor/browser/controller/mouseHandler.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
* Licensed under the MIT License. See License.txt in the project root for license information.
44
*--------------------------------------------------------------------------------------------*/
55

6-
import * as browser from 'vs/base/browser/browser';
76
import * as dom from 'vs/base/browser/dom';
87
import { StandardWheelEvent, IMouseWheelEvent } from 'vs/base/browser/mouseEvent';
98
import { TimeoutTimer } from 'vs/base/common/async';
@@ -119,7 +118,7 @@ export class MouseHandler extends ViewEventHandler {
119118
e.stopPropagation();
120119
}
121120
};
122-
this._register(dom.addDisposableListener(this.viewHelper.viewDomNode, browser.isEdge ? 'mousewheel' : 'wheel', onMouseWheel, { capture: true, passive: false }));
121+
this._register(dom.addDisposableListener(this.viewHelper.viewDomNode, dom.EventType.MOUSE_WHEEL, onMouseWheel, { capture: true, passive: false }));
123122

124123
this._context.addEventHandler(this);
125124
}

src/vs/workbench/browser/parts/editor/tabsTitleControl.ts

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@ export class TabsTitleControl extends TitleControl {
209209
this._register(addDisposableListener(tabsContainer, EventType.SCROLL, () => {
210210
if (hasClass(tabsContainer, 'scroll')) {
211211
tabsScrollbar.setScrollPosition({
212-
scrollLeft: tabsContainer.scrollLeft // during DND the container gets scrolled so we need to update the custom scrollbar
212+
scrollLeft: tabsContainer.scrollLeft // during DND the container gets scrolled so we need to update the custom scrollbar
213213
});
214214
}
215215
}));
@@ -320,6 +320,42 @@ export class TabsTitleControl extends TitleControl {
320320
}
321321
}
322322
}));
323+
324+
// Mouse-wheel support to switch to tabs optionally
325+
this._register(addDisposableListener(tabsContainer, EventType.MOUSE_WHEEL, (e: MouseWheelEvent) => {
326+
const activeEditor = this.group.activeEditor;
327+
if (!activeEditor || this.group.count < 2) {
328+
return; // need at least 2 open editors
329+
}
330+
331+
// Shift-key enables or disables this behaviour depending on the setting
332+
if (this.accessor.partOptions.scrollToSwitchTabs === 'off') {
333+
if (!e.shiftKey) {
334+
return; // 'off': only enable this when Shift-key is pressed
335+
}
336+
} else {
337+
if (e.shiftKey) {
338+
return; // 'on': only enable this when Shift-key is not pressed
339+
}
340+
}
341+
342+
// Figure out scrolling direction
343+
let scrollingUp = e.deltaX < 0 || e.deltaY < 0;
344+
if (this.accessor.partOptions.scrollToSwitchTabs === 'reverse') {
345+
scrollingUp = !scrollingUp;
346+
}
347+
348+
const nextEditor = this.group.getEditorByIndex(this.group.getIndexOfEditor(activeEditor) + (scrollingUp ? -1 : 1));
349+
if (!nextEditor) {
350+
return;
351+
}
352+
353+
// Open it
354+
this.group.openEditor(nextEditor);
355+
356+
// Disable normal scrolling, opening the editor will already reveal it properly
357+
EventHelper.stop(e, true);
358+
}));
323359
}
324360

325361
protected updateEditorActionsToolbar(): void {

src/vs/workbench/browser/workbench.contribution.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,17 @@ import { workbenchConfigurationNodeBase } from 'vs/workbench/common/configuratio
3232
'description': nls.localize('showEditorTabs', "Controls whether opened editors should show in tabs or not."),
3333
'default': true
3434
},
35+
'workbench.editor.scrollToSwitchTabs': {
36+
'type': 'string',
37+
'enum': ['off', 'natural', 'reverse'],
38+
'enumDescriptions': [
39+
nls.localize('workbench.editor.scrollToSwitchTabs.off', "Tabs will reveal when scrolling with the mouse but not open. You can press and hold the Shift-key to switch tabs while scrolling."),
40+
nls.localize('workbench.editor.scrollToSwitchTabs.natural', "Tabs will open when scrolling with the mouse in natural scrolling direction (scroll up to switch to the tab on the left and down for the tab on the right). You can press and hold the Shift-key to disable this behaviour for that duration."),
41+
nls.localize('workbench.editor.scrollToSwitchTabs.reverse', "Tabs will open when scrolling with the mouse in reverse scrolling direction (scroll down to switch to the tab on the left and up for the tab on the right). You can press and hold the Shift-key to disable this behaviour for that duration."),
42+
],
43+
'default': 'off',
44+
'description': nls.localize({ comment: ['This is the description for a setting. Values surrounded by single quotes are not to be translated.'], key: 'scrollToSwitchTabs' }, "Controls wether scrolling over tabs will open them or not. By default tabs will only reveal upon scrolling, but not open. You can press and hold the Shift-key while scrolling to change this behaviour for that duration.")
45+
},
3546
'workbench.editor.highlightModifiedTabs': {
3647
'type': 'boolean',
3748
'description': nls.localize('highlightModifiedTabs', "Controls whether a top border is drawn on modified (dirty) editor tabs or not."),

src/vs/workbench/common/editor.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1303,6 +1303,7 @@ export interface IWorkbenchEditorConfiguration {
13031303

13041304
interface IEditorPartConfiguration {
13051305
showTabs?: boolean;
1306+
scrollToSwitchTabs?: 'off' | 'natural' | 'reverse';
13061307
highlightModifiedTabs?: boolean;
13071308
tabCloseButton?: 'left' | 'right' | 'off';
13081309
tabSizing?: 'fit' | 'shrink';

0 commit comments

Comments
 (0)