From 5bd7b4aaecc10caacec50dc481ec5ac19b1f0cce Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Thu, 28 Aug 2025 10:28:19 -0700 Subject: [PATCH 01/12] Bring back partial wheel tracking Part of microsoft/vscode#224750 --- src/browser/CoreBrowserTerminal.ts | 41 ++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/src/browser/CoreBrowserTerminal.ts b/src/browser/CoreBrowserTerminal.ts index 14ff9433..37b33f7e 100644 --- a/src/browser/CoreBrowserTerminal.ts +++ b/src/browser/CoreBrowserTerminal.ts @@ -646,6 +646,10 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal { if (deltaY === 0) { return false; } + const lines = self._consumeWheelEvent(ev as WheelEvent); + if (lines === 0) { + return false; + } action = deltaY < 0 ? CoreMouseAction.UP : CoreMouseAction.DOWN; but = CoreMouseButton.WHEEL; break; @@ -817,6 +821,11 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal { return false; } + const lines = self._consumeWheelEvent(ev as WheelEvent); + if (lines === 0) { + return false; + } + // Construct and send sequences const sequence = C0.ESC + (this.coreService.decPrivateModes.applicationCursorKeys ? 'O' : '[') + (ev.deltaY < 0 ? 'A' : 'B'); this.coreService.triggerDataEvent(sequence, true); @@ -825,6 +834,38 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal { }, { passive: false })); } + // Stores a partial line amount when scrolling, this is used to keep track of how much of a line + // is scrolled so we can "scroll" over partial lines and feel natural on touchpads. This is a + // quick fix and could have a more robust solution in place that reset the value when needed. + private _wheelPartialScroll: number = 0; + + /** + * Gets the number of pixels scrolled by the mouse event taking into account what type of delta + * is being used. + * @param ev The mouse wheel event. + */ + private _consumeWheelEvent(ev: WheelEvent): number { + // Do nothing if it's not a vertical scroll event + if (ev.deltaY === 0 || ev.shiftKey) { + return 0; + } + + if (!this._coreBrowserService || !this._renderService) { + return 0; + } + // Fallback to WheelEvent.DOM_DELTA_LINE + const targetWheelEventPixels = this._renderService.dimensions.device.cell.height / this._coreBrowserService.dpr; + let amount = 1; + if (ev.deltaMode === WheelEvent.DOM_DELTA_PIXEL) { + amount /= targetWheelEventPixels + 0.0; // Prevent integer division + this._wheelPartialScroll += amount; + amount = Math.floor(Math.abs(this._wheelPartialScroll)) * (this._wheelPartialScroll > 0 ? 1 : -1); + this._wheelPartialScroll %= 1; + } else if (ev.deltaMode === WheelEvent.DOM_DELTA_PAGE) { + amount *= this._bufferService.rows; + } + return amount; + } /** * Tells the renderer to refresh terminal content between two rows (inclusive) at the next From ebddd5d3465b63aaae8379484694ef4a012db4f7 Mon Sep 17 00:00:00 2001 From: Anthony Kim Date: Thu, 28 Aug 2025 22:54:50 -0700 Subject: [PATCH 02/12] Move from CoreBrowerTerminal to CoreMouseService. Still slow though --- src/browser/CoreBrowserTerminal.ts | 43 ++++++------------------- src/common/TestUtils.test.ts | 3 ++ src/common/services/CoreMouseService.ts | 30 +++++++++++++++++ src/common/services/Services.ts | 5 +++ 4 files changed, 48 insertions(+), 33 deletions(-) diff --git a/src/browser/CoreBrowserTerminal.ts b/src/browser/CoreBrowserTerminal.ts index 37b33f7e..6ba27b66 100644 --- a/src/browser/CoreBrowserTerminal.ts +++ b/src/browser/CoreBrowserTerminal.ts @@ -646,7 +646,11 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal { if (deltaY === 0) { return false; } - const lines = self._consumeWheelEvent(ev as WheelEvent); + const lines = self.coreMouseService.consumeWhellEvent( + ev as WheelEvent, + self._renderService?.dimensions?.device?.cell?.height, + self._coreBrowserService?.dpr + ); if (lines === 0) { return false; } @@ -821,7 +825,11 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal { return false; } - const lines = self._consumeWheelEvent(ev as WheelEvent); + const lines = self.coreMouseService.consumeWhellEvent( + ev as WheelEvent, + self._renderService?.dimensions?.device?.cell?.height, + self._coreBrowserService?.dpr + ); if (lines === 0) { return false; } @@ -834,38 +842,7 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal { }, { passive: false })); } - // Stores a partial line amount when scrolling, this is used to keep track of how much of a line - // is scrolled so we can "scroll" over partial lines and feel natural on touchpads. This is a - // quick fix and could have a more robust solution in place that reset the value when needed. - private _wheelPartialScroll: number = 0; - /** - * Gets the number of pixels scrolled by the mouse event taking into account what type of delta - * is being used. - * @param ev The mouse wheel event. - */ - private _consumeWheelEvent(ev: WheelEvent): number { - // Do nothing if it's not a vertical scroll event - if (ev.deltaY === 0 || ev.shiftKey) { - return 0; - } - - if (!this._coreBrowserService || !this._renderService) { - return 0; - } - // Fallback to WheelEvent.DOM_DELTA_LINE - const targetWheelEventPixels = this._renderService.dimensions.device.cell.height / this._coreBrowserService.dpr; - let amount = 1; - if (ev.deltaMode === WheelEvent.DOM_DELTA_PIXEL) { - amount /= targetWheelEventPixels + 0.0; // Prevent integer division - this._wheelPartialScroll += amount; - amount = Math.floor(Math.abs(this._wheelPartialScroll)) * (this._wheelPartialScroll > 0 ? 1 : -1); - this._wheelPartialScroll %= 1; - } else if (ev.deltaMode === WheelEvent.DOM_DELTA_PAGE) { - amount *= this._bufferService.rows; - } - return amount; - } /** * Tells the renderer to refresh terminal content between two rows (inclusive) at the next diff --git a/src/common/TestUtils.test.ts b/src/common/TestUtils.test.ts index 127e1f24..b25a2182 100644 --- a/src/common/TestUtils.test.ts +++ b/src/common/TestUtils.test.ts @@ -66,6 +66,9 @@ export class MockCoreMouseService implements ICoreMouseService { public explainEvents(events: CoreMouseEventType): { [event: string]: boolean } { throw new Error('Method not implemented.'); } + public consumeWhellEvent(ev: WheelEvent, cellHeight: number, dpr: number): number { + return 1; // Return a simple mock value + } } export class MockCharsetService implements ICharsetService { diff --git a/src/common/services/CoreMouseService.ts b/src/common/services/CoreMouseService.ts index f2f02379..a1135a8a 100644 --- a/src/common/services/CoreMouseService.ts +++ b/src/common/services/CoreMouseService.ts @@ -174,6 +174,7 @@ export class CoreMouseService extends Disposable implements ICoreMouseService { private _activeProtocol: string = ''; private _activeEncoding: string = ''; private _lastEvent: ICoreMouseEvent | null = null; + private _wheelPartialScroll: number = 0; private readonly _onProtocolChange = this._register(new Emitter()); public readonly onProtocolChange = this._onProtocolChange.event; @@ -229,6 +230,35 @@ export class CoreMouseService extends Disposable implements ICoreMouseService { this.activeProtocol = 'NONE'; this.activeEncoding = 'DEFAULT'; this._lastEvent = null; + this._wheelPartialScroll = 0; + } + + /** + * Processes a wheel event, accounting for partial scrolls for trackpad, mouse scrolls. + * This prevents hyper-sensitive scrolling in alt buffer. + */ + public consumeWhellEvent(ev: WheelEvent, cellHeight?: number, dpr?: number): number { + // Do nothing if it's not a vertical scroll event + if (ev.deltaY === 0 || ev.shiftKey) { + return 0; + } + + if (cellHeight === undefined || dpr === undefined) { + return 0; + } + + // Fallback to WheelEvent.DOM_DELTA_LINE + const targetWheelEventPixels = cellHeight / dpr; + let amount = 1; + if (ev.deltaMode === WheelEvent.DOM_DELTA_PIXEL) { + amount /= targetWheelEventPixels + 0.0; // Prevent integer division + this._wheelPartialScroll += amount; + amount = Math.floor(Math.abs(this._wheelPartialScroll)) * (this._wheelPartialScroll > 0 ? 1 : -1); + this._wheelPartialScroll %= 1; + } else if (ev.deltaMode === WheelEvent.DOM_DELTA_PAGE) { + amount *= this._bufferService.rows; + } + return amount; } /** diff --git a/src/common/services/Services.ts b/src/common/services/Services.ts index 9c3aebf7..e7ccc241 100644 --- a/src/common/services/Services.ts +++ b/src/common/services/Services.ts @@ -58,6 +58,11 @@ export interface ICoreMouseService { * Human readable version of mouse events. */ explainEvents(events: CoreMouseEventType): { [event: string]: boolean }; + + /** + * Process wheel event taking partial scroll into account. + */ + consumeWhellEvent(ev: WheelEvent, cellHeight?: number, dpr?: number): number; } export const ICoreService = createDecorator('CoreService'); From b104a5b953a22329917b5d22378465279e5b9eaf Mon Sep 17 00:00:00 2001 From: Anthony Kim Date: Thu, 28 Aug 2025 22:56:15 -0700 Subject: [PATCH 03/12] Respect original formatting --- src/browser/CoreBrowserTerminal.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/browser/CoreBrowserTerminal.ts b/src/browser/CoreBrowserTerminal.ts index 6ba27b66..bd513573 100644 --- a/src/browser/CoreBrowserTerminal.ts +++ b/src/browser/CoreBrowserTerminal.ts @@ -843,7 +843,6 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal { } - /** * Tells the renderer to refresh terminal content between two rows (inclusive) at the next * opportunity. From 26ecba8de1f5205c8a8f577c4ebce687ac23be84 Mon Sep 17 00:00:00 2001 From: Anthony Kim Date: Mon, 8 Sep 2025 21:03:05 -0700 Subject: [PATCH 04/12] Fix sluggish mouse problem. Now similar to trackpad --- src/browser/CoreBrowserTerminal.ts | 4 ++-- src/common/TestUtils.test.ts | 2 +- src/common/services/CoreMouseService.ts | 5 +++-- src/common/services/Services.ts | 2 +- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/browser/CoreBrowserTerminal.ts b/src/browser/CoreBrowserTerminal.ts index bd513573..c9349760 100644 --- a/src/browser/CoreBrowserTerminal.ts +++ b/src/browser/CoreBrowserTerminal.ts @@ -646,7 +646,7 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal { if (deltaY === 0) { return false; } - const lines = self.coreMouseService.consumeWhellEvent( + const lines = self.coreMouseService.consumeWheelEvent( ev as WheelEvent, self._renderService?.dimensions?.device?.cell?.height, self._coreBrowserService?.dpr @@ -825,7 +825,7 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal { return false; } - const lines = self.coreMouseService.consumeWhellEvent( + const lines = self.coreMouseService.consumeWheelEvent( ev as WheelEvent, self._renderService?.dimensions?.device?.cell?.height, self._coreBrowserService?.dpr diff --git a/src/common/TestUtils.test.ts b/src/common/TestUtils.test.ts index b25a2182..1ee79e75 100644 --- a/src/common/TestUtils.test.ts +++ b/src/common/TestUtils.test.ts @@ -66,7 +66,7 @@ export class MockCoreMouseService implements ICoreMouseService { public explainEvents(events: CoreMouseEventType): { [event: string]: boolean } { throw new Error('Method not implemented.'); } - public consumeWhellEvent(ev: WheelEvent, cellHeight: number, dpr: number): number { + public consumeWheelEvent(ev: WheelEvent, cellHeight: number, dpr: number): number { return 1; // Return a simple mock value } } diff --git a/src/common/services/CoreMouseService.ts b/src/common/services/CoreMouseService.ts index a1135a8a..7f3d5f39 100644 --- a/src/common/services/CoreMouseService.ts +++ b/src/common/services/CoreMouseService.ts @@ -237,7 +237,7 @@ export class CoreMouseService extends Disposable implements ICoreMouseService { * Processes a wheel event, accounting for partial scrolls for trackpad, mouse scrolls. * This prevents hyper-sensitive scrolling in alt buffer. */ - public consumeWhellEvent(ev: WheelEvent, cellHeight?: number, dpr?: number): number { + public consumeWheelEvent(ev: WheelEvent, cellHeight?: number, dpr?: number): number { // Do nothing if it's not a vertical scroll event if (ev.deltaY === 0 || ev.shiftKey) { return 0; @@ -251,7 +251,8 @@ export class CoreMouseService extends Disposable implements ICoreMouseService { const targetWheelEventPixels = cellHeight / dpr; let amount = 1; if (ev.deltaMode === WheelEvent.DOM_DELTA_PIXEL) { - amount /= targetWheelEventPixels + 0.0; // Prevent integer division + const pixelAmount = ev.deltaY; + amount = pixelAmount / (targetWheelEventPixels + 0.0); // Prevent integer division this._wheelPartialScroll += amount; amount = Math.floor(Math.abs(this._wheelPartialScroll)) * (this._wheelPartialScroll > 0 ? 1 : -1); this._wheelPartialScroll %= 1; diff --git a/src/common/services/Services.ts b/src/common/services/Services.ts index e7ccc241..d47c3bbc 100644 --- a/src/common/services/Services.ts +++ b/src/common/services/Services.ts @@ -62,7 +62,7 @@ export interface ICoreMouseService { /** * Process wheel event taking partial scroll into account. */ - consumeWhellEvent(ev: WheelEvent, cellHeight?: number, dpr?: number): number; + consumeWheelEvent(ev: WheelEvent, cellHeight?: number, dpr?: number): number; } export const ICoreService = createDecorator('CoreService'); From 50df7a69e61a6e49ec8c082231339bbb40bbc026 Mon Sep 17 00:00:00 2001 From: Anthony Kim Date: Mon, 8 Sep 2025 21:06:37 -0700 Subject: [PATCH 05/12] remove unused var --- src/common/services/CoreMouseService.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/common/services/CoreMouseService.ts b/src/common/services/CoreMouseService.ts index 7f3d5f39..bf01d73c 100644 --- a/src/common/services/CoreMouseService.ts +++ b/src/common/services/CoreMouseService.ts @@ -251,8 +251,7 @@ export class CoreMouseService extends Disposable implements ICoreMouseService { const targetWheelEventPixels = cellHeight / dpr; let amount = 1; if (ev.deltaMode === WheelEvent.DOM_DELTA_PIXEL) { - const pixelAmount = ev.deltaY; - amount = pixelAmount / (targetWheelEventPixels + 0.0); // Prevent integer division + amount = ev.deltaY / (targetWheelEventPixels + 0.0); // Prevent integer division this._wheelPartialScroll += amount; amount = Math.floor(Math.abs(this._wheelPartialScroll)) * (this._wheelPartialScroll > 0 ? 1 : -1); this._wheelPartialScroll %= 1; From d862c823861ce04ef304bec2b1f028f69e3c98da Mon Sep 17 00:00:00 2001 From: Anthony Kim Date: Mon, 8 Sep 2025 21:14:20 -0700 Subject: [PATCH 06/12] no stale comments --- src/common/TestUtils.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/TestUtils.test.ts b/src/common/TestUtils.test.ts index 1ee79e75..499fb787 100644 --- a/src/common/TestUtils.test.ts +++ b/src/common/TestUtils.test.ts @@ -67,7 +67,7 @@ export class MockCoreMouseService implements ICoreMouseService { throw new Error('Method not implemented.'); } public consumeWheelEvent(ev: WheelEvent, cellHeight: number, dpr: number): number { - return 1; // Return a simple mock value + return 1; } } From cf6b868dfbf1f10885e53b3c841f188ff3204037 Mon Sep 17 00:00:00 2001 From: Anthony Kim Date: Tue, 9 Sep 2025 11:51:27 -0700 Subject: [PATCH 07/12] fastScrollModifier seems deprecated --- src/common/services/CoreMouseService.ts | 31 +++++++++++++++++++++---- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/src/common/services/CoreMouseService.ts b/src/common/services/CoreMouseService.ts index bf01d73c..e777f007 100644 --- a/src/common/services/CoreMouseService.ts +++ b/src/common/services/CoreMouseService.ts @@ -2,7 +2,7 @@ * Copyright (c) 2019 The xterm.js authors. All rights reserved. * @license MIT */ -import { IBufferService, ICoreService, ICoreMouseService } from 'common/services/Services'; +import { IBufferService, ICoreService, ICoreMouseService, IOptionsService } from 'common/services/Services'; import { ICoreMouseProtocol, ICoreMouseEvent, CoreMouseEncoding, CoreMouseEventType, CoreMouseButton, CoreMouseAction } from 'common/Types'; import { Disposable } from 'vs/base/common/lifecycle'; import { Emitter } from 'vs/base/common/event'; @@ -181,7 +181,8 @@ export class CoreMouseService extends Disposable implements ICoreMouseService { constructor( @IBufferService private readonly _bufferService: IBufferService, - @ICoreService private readonly _coreService: ICoreService + @ICoreService private readonly _coreService: ICoreService, + @IOptionsService private readonly _optionsService: IOptionsService ) { super(); // register default protocols and encodings @@ -247,11 +248,17 @@ export class CoreMouseService extends Disposable implements ICoreMouseService { return 0; } - // Fallback to WheelEvent.DOM_DELTA_LINE const targetWheelEventPixels = cellHeight / dpr; - let amount = 1; + let amount = this._applyScrollModifier(ev.deltaY, ev); + if (ev.deltaMode === WheelEvent.DOM_DELTA_PIXEL) { - amount = ev.deltaY / (targetWheelEventPixels + 0.0); // Prevent integer division + amount /= (targetWheelEventPixels + 0.0); // Prevent integer division + + const isLikelyTrackpad = Math.abs(ev.deltaY) < 50; + if (isLikelyTrackpad) { + amount *= 0.3; + } + this._wheelPartialScroll += amount; amount = Math.floor(Math.abs(this._wheelPartialScroll)) * (this._wheelPartialScroll > 0 ? 1 : -1); this._wheelPartialScroll %= 1; @@ -261,6 +268,20 @@ export class CoreMouseService extends Disposable implements ICoreMouseService { return amount; } + private _applyScrollModifier(amount: number, ev: WheelEvent): number { + const modifier = this._optionsService.rawOptions.fastScrollModifier; // QUESTION: This is always alt. Seems deprecated via: https://github.com/xtermjs/xterm.js/blob/5.5.0/src/browser/Viewport.ts + console.log('what is this modifier: ', modifier); + + // Multiply the scroll speed when the modifier key is pressed + if ((modifier === 'alt' && ev.altKey) || + (modifier === 'ctrl' && ev.ctrlKey) || + (modifier === 'shift' && ev.shiftKey)) { + return amount * this._optionsService.rawOptions.fastScrollSensitivity * this._optionsService.rawOptions.scrollSensitivity; + } + + return amount * this._optionsService.rawOptions.scrollSensitivity; + } + /** * Triggers a mouse event to be sent. * From 03ce26c6975ad2f71276a87e984bf9bec0503db5 Mon Sep 17 00:00:00 2001 From: Anthony Kim Date: Tue, 9 Sep 2025 11:56:28 -0700 Subject: [PATCH 08/12] Questions, possible concern --- src/common/services/CoreMouseService.ts | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/common/services/CoreMouseService.ts b/src/common/services/CoreMouseService.ts index e777f007..da94ed97 100644 --- a/src/common/services/CoreMouseService.ts +++ b/src/common/services/CoreMouseService.ts @@ -177,7 +177,7 @@ export class CoreMouseService extends Disposable implements ICoreMouseService { private _wheelPartialScroll: number = 0; private readonly _onProtocolChange = this._register(new Emitter()); - public readonly onProtocolChange = this._onProtocolChange.event; + public readonly onProtocolChange = this._onProtocolChange.event; constructor( @IBufferService private readonly _bufferService: IBufferService, @@ -270,12 +270,16 @@ export class CoreMouseService extends Disposable implements ICoreMouseService { private _applyScrollModifier(amount: number, ev: WheelEvent): number { const modifier = this._optionsService.rawOptions.fastScrollModifier; // QUESTION: This is always alt. Seems deprecated via: https://github.com/xtermjs/xterm.js/blob/5.5.0/src/browser/Viewport.ts - console.log('what is this modifier: ', modifier); + // Problem is that modifier always seem 'alt' even when ev.ctrlKey is true, for example. + // Maybe this doesnt matter because all of alt, ctrl, shift does same operation? // Multiply the scroll speed when the modifier key is pressed if ((modifier === 'alt' && ev.altKey) || - (modifier === 'ctrl' && ev.ctrlKey) || - (modifier === 'shift' && ev.shiftKey)) { + (modifier === 'ctrl' && ev.ctrlKey) || + (modifier === 'shift' && ev.shiftKey)) { + + console.log('fast scroll sensitivity: ', this._optionsService.rawOptions.fastScrollSensitivity); + console.log('regular scroll sensitivity: ', this._optionsService.rawOptions.scrollSensitivity); return amount * this._optionsService.rawOptions.fastScrollSensitivity * this._optionsService.rawOptions.scrollSensitivity; } From 1a6a807f6816de4d14a5138817afa8dcc5df595d Mon Sep 17 00:00:00 2001 From: Anthony Kim Date: Tue, 9 Sep 2025 11:59:29 -0700 Subject: [PATCH 09/12] Remove stale comment --- src/common/services/CoreMouseService.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/common/services/CoreMouseService.ts b/src/common/services/CoreMouseService.ts index da94ed97..99cd1fc5 100644 --- a/src/common/services/CoreMouseService.ts +++ b/src/common/services/CoreMouseService.ts @@ -278,8 +278,6 @@ export class CoreMouseService extends Disposable implements ICoreMouseService { (modifier === 'ctrl' && ev.ctrlKey) || (modifier === 'shift' && ev.shiftKey)) { - console.log('fast scroll sensitivity: ', this._optionsService.rawOptions.fastScrollSensitivity); - console.log('regular scroll sensitivity: ', this._optionsService.rawOptions.scrollSensitivity); return amount * this._optionsService.rawOptions.fastScrollSensitivity * this._optionsService.rawOptions.scrollSensitivity; } From 38bee71630a4680cb86b1df00adfd1b9a28973c7 Mon Sep 17 00:00:00 2001 From: Anthony Kim Date: Tue, 9 Sep 2025 12:00:19 -0700 Subject: [PATCH 10/12] More clear comments --- src/common/services/CoreMouseService.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/services/CoreMouseService.ts b/src/common/services/CoreMouseService.ts index 99cd1fc5..9b74daeb 100644 --- a/src/common/services/CoreMouseService.ts +++ b/src/common/services/CoreMouseService.ts @@ -271,7 +271,7 @@ export class CoreMouseService extends Disposable implements ICoreMouseService { private _applyScrollModifier(amount: number, ev: WheelEvent): number { const modifier = this._optionsService.rawOptions.fastScrollModifier; // QUESTION: This is always alt. Seems deprecated via: https://github.com/xtermjs/xterm.js/blob/5.5.0/src/browser/Viewport.ts // Problem is that modifier always seem 'alt' even when ev.ctrlKey is true, for example. - // Maybe this doesnt matter because all of alt, ctrl, shift does same operation? + // May need to tweak conditional to: if any of `ev.altKey || ev.ctrlKey || ev.shiftKey` is true // Multiply the scroll speed when the modifier key is pressed if ((modifier === 'alt' && ev.altKey) || From e4f222f6b00ed853895b154f65c86d0a2a742312 Mon Sep 17 00:00:00 2001 From: Anthony Kim Date: Tue, 9 Sep 2025 12:03:51 -0700 Subject: [PATCH 11/12] Make test happy --- src/common/services/CoreMouseService.test.ts | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/common/services/CoreMouseService.test.ts b/src/common/services/CoreMouseService.test.ts index 34710897..3b79596d 100644 --- a/src/common/services/CoreMouseService.test.ts +++ b/src/common/services/CoreMouseService.test.ts @@ -3,13 +3,14 @@ * @license MIT */ import { CoreMouseService } from 'common/services/CoreMouseService'; -import { MockCoreService, MockBufferService } from 'common/TestUtils.test'; +import { MockCoreService, MockBufferService, MockOptionsService } from 'common/TestUtils.test'; import { assert } from 'chai'; import { ICoreMouseEvent, CoreMouseEventType, CoreMouseButton, CoreMouseAction } from 'common/Types'; // needed mock services const bufferService = new MockBufferService(300, 100); const coreService = new MockCoreService(); +const optionsService = new MockOptionsService(); function toBytes(s: string | undefined): number[] { if (!s) { @@ -24,20 +25,20 @@ function toBytes(s: string | undefined): number[] { describe('CoreMouseService', () => { it('init', () => { - const cms = new CoreMouseService(bufferService, coreService); + const cms = new CoreMouseService(bufferService, coreService, optionsService); assert.equal(cms.activeEncoding, 'DEFAULT'); assert.equal(cms.activeProtocol, 'NONE'); }); it('default protocols - NONE, X10, VT200, DRAG, ANY', () => { - const cms = new CoreMouseService(bufferService, coreService); + const cms = new CoreMouseService(bufferService, coreService, optionsService); assert.deepEqual(Object.keys((cms as any)._protocols), ['NONE', 'X10', 'VT200', 'DRAG', 'ANY']); }); it('default encodings - DEFAULT, SGR', () => { - const cms = new CoreMouseService(bufferService, coreService); + const cms = new CoreMouseService(bufferService, coreService, optionsService); assert.deepEqual(Object.keys((cms as any)._encodings), ['DEFAULT', 'SGR', 'SGR_PIXELS']); }); it('protocol/encoding setter, reset', () => { - const cms = new CoreMouseService(bufferService, coreService); + const cms = new CoreMouseService(bufferService, coreService, optionsService); cms.activeEncoding = 'SGR'; cms.activeProtocol = 'ANY'; assert.equal(cms.activeEncoding, 'SGR'); @@ -49,19 +50,19 @@ describe('CoreMouseService', () => { assert.throws(() => { cms.activeProtocol = 'xyz'; }, 'unknown protocol "xyz"'); }); it('addEncoding', () => { - const cms = new CoreMouseService(bufferService, coreService); + const cms = new CoreMouseService(bufferService, coreService, optionsService); cms.addEncoding('XYZ', (e: ICoreMouseEvent) => ''); cms.activeEncoding = 'XYZ'; assert.equal(cms.activeEncoding, 'XYZ'); }); it('addProtocol', () => { - const cms = new CoreMouseService(bufferService, coreService); + const cms = new CoreMouseService(bufferService, coreService, optionsService); cms.addProtocol('XYZ', { events: CoreMouseEventType.NONE, restrict: (e: ICoreMouseEvent) => false }); cms.activeProtocol = 'XYZ'; assert.equal(cms.activeProtocol, 'XYZ'); }); it('onProtocolChange', () => { - const cms = new CoreMouseService(bufferService, coreService); + const cms = new CoreMouseService(bufferService, coreService, optionsService); const wantedEvents: CoreMouseEventType[] = []; cms.onProtocolChange(events => wantedEvents.push(events)); cms.activeProtocol = 'NONE'; @@ -76,7 +77,7 @@ describe('CoreMouseService', () => { let cms: CoreMouseService; let reports: string[]; beforeEach(() => { - cms = new CoreMouseService(bufferService, coreService); + cms = new CoreMouseService(bufferService, coreService, optionsService); reports = []; coreService.triggerDataEvent = (data: string, userInput?: boolean) => reports.push(data); coreService.triggerBinaryEvent = (data: string) => reports.push(data); From 9c42fb348b38a9fa7a1cc817edcb63059652dfc0 Mon Sep 17 00:00:00 2001 From: Anthony Kim Date: Tue, 9 Sep 2025 13:21:37 -0700 Subject: [PATCH 12/12] ignore fastScrollModifier --- src/common/services/CoreMouseService.ts | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/src/common/services/CoreMouseService.ts b/src/common/services/CoreMouseService.ts index 9b74daeb..a10ddafb 100644 --- a/src/common/services/CoreMouseService.ts +++ b/src/common/services/CoreMouseService.ts @@ -269,18 +269,10 @@ export class CoreMouseService extends Disposable implements ICoreMouseService { } private _applyScrollModifier(amount: number, ev: WheelEvent): number { - const modifier = this._optionsService.rawOptions.fastScrollModifier; // QUESTION: This is always alt. Seems deprecated via: https://github.com/xtermjs/xterm.js/blob/5.5.0/src/browser/Viewport.ts - // Problem is that modifier always seem 'alt' even when ev.ctrlKey is true, for example. - // May need to tweak conditional to: if any of `ev.altKey || ev.ctrlKey || ev.shiftKey` is true - // Multiply the scroll speed when the modifier key is pressed - if ((modifier === 'alt' && ev.altKey) || - (modifier === 'ctrl' && ev.ctrlKey) || - (modifier === 'shift' && ev.shiftKey)) { - + if (ev.altKey || ev.ctrlKey || ev.shiftKey) { return amount * this._optionsService.rawOptions.fastScrollSensitivity * this._optionsService.rawOptions.scrollSensitivity; } - return amount * this._optionsService.rawOptions.scrollSensitivity; }