Change:
Issue Type: <bFeature Request</bCurrently it's unclear and difficult to handle scrolling events inside an output which is rendered in the webview due to the disadvantage of our current architecture: we listen to event in the webview and scroll the list view in the main thread accordingly. It means if users attempt to scroll in a native scrollable element, the element will be scrolled in the webview, and also trigger the whole editor to scroll. Events triggered when users scroll on a scrollable element events come right after events, usually in a few milliseconds. If users trigger scroll (by mouse wheel or touchpad) on a non-scrollable element, there are only events. For our scenario, we want to emit events to the main thread, only when there is no event followed right after. This can be archived by delaying the wheel event message to the main thread The catch of this solution is how long should we delay. Usually a scroll event comes after a wheel event in just a few ms but it's not guaranteed. Renderers handle the scrolling themselves. For example, a renderer can stop sending event on a scrollable element. The challenge for renderers is they need to be keep track of any element with it renders and stop events only when necessary. VS Code version: Code - Insiders 1.44.0-insider (, 2020-03-27T05:28:16.333Z) OS version: Darwin x64 19.2.0 <!-- generated by issue reporter --
cc as you mentioned that it would be painful to write a list view in the output.
I would suggest listening to the wheel event, and triggering a scroll in the notebook if there's no parent element that will scroll. You should be able to tell that with something like
thanks very much, the suggestion is pretty solid. ! The only update to 's snippet above is the scroll should stop at the container of each output container instead of going all the way up to body (potentially). The event listener should also then be registered only in notebook webview other than all webviews.

Discussion:
data: DOM.Dimension; } <ins> export interface IWheelMessage { __vscode_notebook_message: boolean; type: 'did-scroll-wheel'; payload: any; } </ins> export interface IScrollAckMessage { __vscode_notebook_message: boolean;

resources: string[]; } <del> type IMessage = IDimentionMessage | IScrollAckMessage; </del> <ins> type IMessage = IDimentionMessage | IScrollAckMessage | IWheelMessage; </ins> let version = 0; export class BackLayerWebView extends Disposable {

observers.push(resizeObserver); } <ins> function scrollWillGoToParent(event) { for (let node = event.target; node; node = node.parentNode) { if (node.id === 'container') { return false; } console.log(node, node.parentNode, node.scrollTop, node.scrollHeight, node.clientHeight); if (event.deltaY < 0 && node.scrollTop > 0) { return true; } if (event.deltaY > 0 && node.scrollTop + node.clientHeight < node.scrollHeight) { return true; } } return false; } const handleWheel = (event) => { if (event.defaultPrevented || scrollWillGoToParent(event)) { return; } vscode.postMessage({ __vscode_notebook_message: true, type: 'did-scroll-wheel', payload: { deltaMode: event.deltaMode, deltaX: event.deltaX, deltaY: event.deltaY, deltaZ: event.deltaZ, detail: event.detail, type: event.type } }); }; window.addEventListener('wheel', handleWheel); </ins> window.addEventListener('message', event => { let id = event.data.id;

openerService.open(link, { fromUserGesture: true }); })); <del> this._register(this.webview.onDidWheel(e => { this.notebookEditor.triggerScroll(e); })); </del> this._register(this.webview.onMessage((data: IMessage) => { if (data.__vscode_notebook_message) { if (data.type === 'dimension') {

// const date = new Date(); // const top = data.data.top; // console.log('ack top ', top, ' version: ', data.version, ' - ', date.getMinutes() + ':' + date.getSeconds() + ':' + date.getMilliseconds()); <ins> } else if (data.type === 'did-scroll-wheel') { this.notebookEditor.triggerScroll(data.payload); </ins> } return; }