microsoft / microsoft/vscode

Terminal: expose xterm.js `mouseEventsRequireAlt` as a setting so mouse reporting never costs text selection

Open
#330,052 0 comments 0 reactions 1 assignee Claimed by @anthonykim1 View on GitHub
Dominant language
TypeScript
Stars
193k
Forks
42.4k
PR merge metrics
PR metrics pending

Description

### Problem

When a TUI application enables mouse reporting (`CSI ? 1000 h` and friends), the integrated terminal stops creating selections: `mousedown` is forwarded to the application instead. That is correct behaviour, but it means a single application choice silently removes the user's ability to select and copy text with the mouse — with no setting to opt out.

This is increasingly common: full-screen TUIs (Claude Code, various agents and TUI editors) arm mouse tracking by default, and users discover the terminal "can no longer select text" without any way to relate it to the application.

`Shift`+drag is a workaround, but it is undiscoverable and it is not what people reach for.

### Proposal

xterm.js already implements exactly the arbitration needed, in `SelectionService.shouldForceSelection()` / the `mouseEventsRequireAlt` option: when it is enabled, mouse reporting stays armed but only takes the click while the modifier is held, so plain drags keep selecting.

The option is present in the `@xterm/xterm` build VS Code ships, but it is never set — I could not find a single reference to `mouseEventsRequireAlt` anywhere in the shipped `out/` tree, so it stays at its default (`false`).

Exposing it would be a small, local change:

```jsonc
// proposed
"terminal.integrated.mouseEventsRequireModifier": false // default: today's behaviour
```

When `true`, pass `mouseEventsRequireAlt: true` to the `Terminal` constructor / `options`. Users who prefer selection over in-app clicking flip one setting, once, and it applies to every TUI they run — instead of chasing a per-application environment variable each time.

### Why a setting rather than per-application handling

The terminal is the only layer that can arbitrate this: applications legitimately want mouse events, and users legitimately want selection. Today the application wins unconditionally and the user has no vote.

### Extra context for the browser case (code-server)

In `code-server` the impact is larger than on the desktop: the standard copy paths already go through an async IPC hop that breaks the clipboard user-gesture, so users end up relying on the browser's native DOM selection — which is precisely what disappears when mouse reporting is armed. Losing the selection there removes the last working copy path to the OS clipboard.

### Environment

- VS Code 1.131.0 as bundled by code-server 4.131.0, xterm.js `@xterm/xterm` 6.1.0-beta.291
- Verified with the shipped bundle loaded standalone and driven with real mouse events: with no tracking a plain drag selects; with `?1000h ?1006h` or the full set it selects nothing; `Shift`+drag selects in every case.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.