Skip to content

Commit

Permalink
tabs - add setting to switch tabs with mouse-wheel (#13902)
Browse files Browse the repository at this point in the history
  • Loading branch information
bpasero committed Apr 14, 2020
1 parent c8826e4 commit 0940e0f
Show file tree
Hide file tree
Showing 6 changed files with 52 additions and 5 deletions.
1 change: 1 addition & 0 deletions src/vs/base/browser/dom.ts
Expand Up @@ -822,6 +822,7 @@ export const EventType = {
MOUSE_OUT: 'mouseout',
MOUSE_ENTER: 'mouseenter',
MOUSE_LEAVE: 'mouseleave',
MOUSE_WHEEL: browser.isEdge ? 'mousewheel' : 'wheel',
POINTER_UP: 'pointerup',
POINTER_DOWN: 'pointerdown',
POINTER_MOVE: 'pointermove',
Expand Down
3 changes: 1 addition & 2 deletions src/vs/base/browser/ui/scrollbar/scrollableElement.ts
Expand Up @@ -4,7 +4,6 @@
*--------------------------------------------------------------------------------------------*/

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

this._mouseWheelToDispose.push(dom.addDisposableListener(this._listenOnDomNode, isEdge ? 'mousewheel' : 'wheel', onMouseWheel, { passive: false }));
this._mouseWheelToDispose.push(dom.addDisposableListener(this._listenOnDomNode, dom.EventType.MOUSE_WHEEL, onMouseWheel, { passive: false }));
}
}

Expand Down
3 changes: 1 addition & 2 deletions src/vs/editor/browser/controller/mouseHandler.ts
Expand Up @@ -3,7 +3,6 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

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

this._context.addEventHandler(this);
}
Expand Down
38 changes: 37 additions & 1 deletion src/vs/workbench/browser/parts/editor/tabsTitleControl.ts
Expand Up @@ -209,7 +209,7 @@ export class TabsTitleControl extends TitleControl {
this._register(addDisposableListener(tabsContainer, EventType.SCROLL, () => {
if (hasClass(tabsContainer, 'scroll')) {
tabsScrollbar.setScrollPosition({
scrollLeft: tabsContainer.scrollLeft // during DND the container gets scrolled so we need to update the custom scrollbar
scrollLeft: tabsContainer.scrollLeft // during DND the container gets scrolled so we need to update the custom scrollbar
});
}
}));
Expand Down Expand Up @@ -320,6 +320,42 @@ export class TabsTitleControl extends TitleControl {
}
}
}));

// Mouse-wheel support to switch to tabs optionally
this._register(addDisposableListener(tabsContainer, EventType.MOUSE_WHEEL, (e: MouseWheelEvent) => {
const activeEditor = this.group.activeEditor;
if (!activeEditor || this.group.count < 2) {
return; // need at least 2 open editors
}

// Shift-key enables or disables this behaviour depending on the setting
if (this.accessor.partOptions.scrollToSwitchTabs === 'off') {
if (!e.shiftKey) {
return; // 'off': only enable this when Shift-key is pressed
}
} else {
if (e.shiftKey) {
return; // 'on': only enable this when Shift-key is not pressed
}
}

// Figure out scrolling direction
let scrollingUp = e.deltaX < 0 || e.deltaY < 0;
if (this.accessor.partOptions.scrollToSwitchTabs === 'reverse') {
scrollingUp = !scrollingUp;
}

const nextEditor = this.group.getEditorByIndex(this.group.getIndexOfEditor(activeEditor) + (scrollingUp ? -1 : 1));
if (!nextEditor) {
return;
}

// Open it
this.group.openEditor(nextEditor);

// Disable normal scrolling, opening the editor will already reveal it properly
EventHelper.stop(e, true);
}));
}

protected updateEditorActionsToolbar(): void {
Expand Down
11 changes: 11 additions & 0 deletions src/vs/workbench/browser/workbench.contribution.ts
Expand Up @@ -32,6 +32,17 @@ import { workbenchConfigurationNodeBase } from 'vs/workbench/common/configuratio
'description': nls.localize('showEditorTabs', "Controls whether opened editors should show in tabs or not."),
'default': true
},
'workbench.editor.scrollToSwitchTabs': {
'type': 'string',
'enum': ['off', 'natural', 'reverse'],
'enumDescriptions': [
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."),
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."),
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."),
],
'default': 'off',
'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.")
},
'workbench.editor.highlightModifiedTabs': {
'type': 'boolean',
'description': nls.localize('highlightModifiedTabs', "Controls whether a top border is drawn on modified (dirty) editor tabs or not."),
Expand Down
1 change: 1 addition & 0 deletions src/vs/workbench/common/editor.ts
Expand Up @@ -1303,6 +1303,7 @@ export interface IWorkbenchEditorConfiguration {

interface IEditorPartConfiguration {
showTabs?: boolean;
scrollToSwitchTabs?: 'off' | 'natural' | 'reverse';
highlightModifiedTabs?: boolean;
tabCloseButton?: 'left' | 'right' | 'off';
tabSizing?: 'fit' | 'shrink';
Expand Down

0 comments on commit 0940e0f

Please sign in to comment.