Fix mouseEventsRequireAlt by stripping alt from PTY mouse reports.
Alt is only used locally to gate passthrough; applications like tmux ignore alt-modified SGR sequences. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -290,4 +290,46 @@ describe('MouseService mouseEventsRequireAlt', () => {
|
||||
assert.isTrue(element.classList.contains('enable-mouse-events'));
|
||||
assert.equal(selectionService.disableCount, 2);
|
||||
});
|
||||
|
||||
it('should strip alt modifier from forwarded mouse reports', () => {
|
||||
const mouseStateService = new MouseStateService();
|
||||
mouseStateService.activeProtocol = 'ANY';
|
||||
mouseStateService.activeEncoding = 'SGR';
|
||||
const optionsService = new OptionsService({ mouseEventsRequireAlt: true });
|
||||
const reports: string[] = [];
|
||||
const mouseService = new MouseService(
|
||||
new MockRenderService(),
|
||||
{
|
||||
getMouseReportCoords: () => ({ col: 0, row: 0, x: 0, y: 0 })
|
||||
} as any,
|
||||
mouseStateService,
|
||||
{
|
||||
triggerDataEvent: (data: string) => reports.push(data),
|
||||
triggerBinaryEvent: () => {},
|
||||
decPrivateModes: { applicationCursorKeys: false }
|
||||
} as any,
|
||||
bufferService,
|
||||
optionsService,
|
||||
new TestSelectionService(),
|
||||
logService,
|
||||
new MockCoreBrowserService()
|
||||
);
|
||||
const ctx = {
|
||||
target: {
|
||||
screenElement: createTestMouseTargetElement()
|
||||
},
|
||||
requestedEvents: {}
|
||||
} as any;
|
||||
|
||||
const sent = (mouseService as any)._sendEvent(ctx, {
|
||||
type: 'mousedown',
|
||||
button: 0,
|
||||
altKey: true,
|
||||
ctrlKey: false,
|
||||
shiftKey: false
|
||||
} as MouseEvent);
|
||||
|
||||
assert.isTrue(sent);
|
||||
assert.deepEqual(reports, ['\x1b[<0;1;1M']);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -163,6 +163,12 @@ export class MouseService implements IMouseService {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Alt is only used locally to gate mouse passthrough; do not forward it to the
|
||||
// application (e.g. tmux ignores alt-modified mouse reports).
|
||||
const stripAltFromReport = but !== CoreMouseButton.WHEEL
|
||||
&& this._optionsService.rawOptions.mouseEventsRequireAlt
|
||||
&& this._mouseStateService.areMouseEventsActive;
|
||||
|
||||
return this._triggerMouseEvent({
|
||||
col: pos.col,
|
||||
row: pos.row,
|
||||
@@ -171,7 +177,7 @@ export class MouseService implements IMouseService {
|
||||
button: but,
|
||||
action,
|
||||
ctrl: ev.ctrlKey,
|
||||
alt: ev.altKey,
|
||||
alt: stripAltFromReport ? false : ev.altKey,
|
||||
shift: ev.shiftKey
|
||||
});
|
||||
}
|
||||
|
||||
Vendored
+2
-1
@@ -139,7 +139,8 @@ declare module '@xterm/headless' {
|
||||
/**
|
||||
* When enabled and the terminal is in mouse events mode, mouse click, drag,
|
||||
* and move events are only sent to the underlying application when the alt
|
||||
* key is held. Wheel events are not affected. This allows normal text
|
||||
* key is held. The alt key is not included in the mouse reports sent to the
|
||||
* application. Wheel events are not affected. This allows normal text
|
||||
* selection by default while still supporting application mouse interaction
|
||||
* and scrolling when holding alt. When enabled, this takes precedence over
|
||||
* `macOptionClickForcesSelection`.
|
||||
|
||||
Vendored
+2
-1
@@ -209,7 +209,8 @@ declare module '@xterm/xterm' {
|
||||
/**
|
||||
* When enabled and the terminal is in mouse events mode, mouse click, drag,
|
||||
* and move events are only sent to the underlying application when the alt
|
||||
* key is held. Wheel events are not affected. This allows normal text
|
||||
* key is held. The alt key is not included in the mouse reports sent to the
|
||||
* application. Wheel events are not affected. This allows normal text
|
||||
* selection by default while still supporting application mouse interaction
|
||||
* and scrolling when holding alt. When enabled, this takes precedence over
|
||||
* `macOptionClickForcesSelection`.
|
||||
|
||||
Reference in New Issue
Block a user