Skip to content

Terminal: report the mouse to programs that ask for it - #2902

Open
insjang wants to merge 1 commit into
eclipse-platform:masterfrom
insjang:mouse-reporting
Open

insjang wants to merge 1 commit into
eclipse-platform:masterfrom
insjang:mouse-reporting

Conversation

@insjang

@insjang insjang commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

Depends on #2901 (the DEC private mode parsing change): ncurses turns the mouse on with CSI ? 1006 ; 1000 h, which needs every parameter of a set/reset to be taken. This PR shows that commit as well until #2901 is merged; only the second commit is new here.

Programs that draw their own screen — htop, ncurses menus, and lately CLIs with clickable options and wheel scrolling — ask the terminal for mouse events with DEC modes 1000 (presses and releases), 1002 (also drags) and 1003 (every move), in xterm's legacy encoding or the SGR one (mode 1006). The terminal ignored the request and kept every click for its own selection, so such programs could not be clicked on or scrolled.

  • The canvas hands presses, releases, moves and the wheel to the control while a program has asked for them, with the Alt and Ctrl keys folded into the button as xterm does.
  • Shift keeps the mouse for the terminal — the convention every terminal uses to still allow a selection while a program is listening.
  • A press that went to the program takes the terminal's selection away and moves the selection anchor to the click, so a later shift-drag starts from where the user last clicked.
  • A release goes wherever its press went, whatever the keyboard state by then, so press and release always reach the same side.
  • Mode 1004 reports focus gained/lost; mode 2026 (synchronized output) lets a program mark a redraw, during which the view leaves the screen alone rather than showing it half drawn.

Tests: MouseReportTest (both encodings, modifiers, wide columns) and mode handling in VT100EmulatorTest.

insjang added a commit to insjang/eclipse.platform that referenced this pull request Sep 3, 2026
Same cross-bundle package-private access problem as mouseReport in
eclipse-platform#2902 -- the test bundle is a separate OSGi bundle, so package-private
static does not reach it even under the same package name.
insjang added a commit to insjang/eclipse.platform that referenced this pull request Sep 28, 2026
Same cross-bundle package-private access problem as mouseReport in
eclipse-platform#2902 -- the test bundle is a separate OSGi bundle, so package-private
static does not reach it even under the same package name.
@insjang
insjang force-pushed the mouse-reporting branch 2 times, most recently from 341beec to ff61a3f Compare September 28, 2026 10:13
insjang added a commit to insjang/eclipse.platform that referenced this pull request Sep 30, 2026
Same cross-bundle package-private access problem as mouseReport in
eclipse-platform#2902 -- the test bundle is a separate OSGi bundle, so package-private
static does not reach it even under the same package name.
@insjang

insjang commented Nov 4, 2026

Copy link
Copy Markdown
Contributor Author

Rebased on master (with #2894 in) on top of the rebased #2901, so this PR shows two commits until #2901 is merged; its own is bb94bf9, the three earlier commits squashed. All terminal tests pass.

How to test, in a runtime Eclipse with this org.eclipse.terminal.control, Terminal view, local shell:

  1. Clicks: run htop and click a process, or a column header to sort.
    Expected: htop selects the process or sorts. Before this change the click only started a terminal selection.
  2. Wheel: in htop, or less with LESS=--mouse, turn the wheel.
    Expected: the program scrolls its list or text.
  3. Drag and modifiers (1002, SGR 1006): mc, drag in a panel; ctrl+click, alt+click.
    Expected: the program sees the drag and the modifiers.
  4. Shift keeps the mouse for the terminal: in htop, shift+drag over some text, then copy.
    Expected: a normal terminal selection, the program does not see the drag.
  5. Focus (1004): printf '\e[?1004h'; cat -v, click another view and back.
    Expected: ^[[O and ^[[I appear. Ctrl+C, then printf '\e[?1004l'.
  6. Reset on a new connection: run printf '\e[?1000h\e[?1004h\e[?2026h', disconnect the terminal, click and switch views while disconnected, connect again.
    Expected: no exception in the Error Log, clicks select text again, and the screen is not frozen.

Unit tests: MouseReportTest (both encodings, modifiers, columns past 223) and the mode handling in VT100EmulatorTest.

@github-actions

github-actions Bot commented Nov 4, 2026 •

Copy link
Copy Markdown
Contributor

Test Results

    54 files  ± 0      54 suites  ±0   32m 11s ⏱️ - 6m 22s
 5 011 tests + 7   4 988 ✅ + 6   22 💤 ±0  1 ❌ +1 
12 924 runs  +21  12 769 ✅ +20  154 💤 ±0  1 ❌ +1 

For more details on these failures, see this check.

Results for commit 77dc7d0. ± Comparison against base commit bc125e3.

♻️ This comment has been updated with latest results.

@akurtakov akurtakov left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, clicking and scrolling in htop, mc and Vim is a big step, and Shift keeping the mouse for the terminal's own selection is the right convention. One scope request inline, plus a question and some small things:

  • Question: while a program listens, a middle-click is reported to it and also pastes (TabFolderManager has its own button-2 listener), and a right-click is reported and also opens the context menu. In Vim with mouse=a a middle-click moves the cursor and pastes. xterm and GNOME Terminal give these clicks to the program alone while it listens, and Shift gets the terminal's behaviour back; should it be the same here?
  • fMouseMode and fSgrMouseEncoding are written by the reader job and read on the display thread, like fBracketedPaste in #2901; please make them volatile too.
  • Nits: @since 5.6 on the new ITerminalControlForText methods names a version that doesn't exist (the bundle is at 1.2, and it's an internal interface, so the tag can go), and fFocusReporting would read better with the other fields at the top.

@insjang

insjang commented Nov 6, 2026

Copy link
Copy Markdown
Contributor Author

Thanks for the review. Pushed as a3ff4e5:

  • Middle and right click: yes, the same as xterm and GNOME Terminal now. A click the program takes is the program's alone: the canvas reports it in a listener that runs before every other and stops the event there, so the middle-click does not also paste, the right-click opens no context menu (the menu key still does), and neither a double-click nor the copy on release acts on it. Shift gives the terminal's behaviour back, for the wheel too. TextCanvasMouseUITest checks both.
  • fMouseMode and fSgrMouseEncoding are volatile, and so is fApplicationCursorKeys, which the reader job writes the same way. All fields the reader writes on the control are now volatile or under the cursor lock.
  • The @SInCE tags are gone and the fields are at the top.

While going over it I also fixed: positions are now the program's screen, not the view (with history above the screen the view rarely starts on a whole line, so a click near the bottom of a row went one row down), a click over history the user scrolled back to stays with the terminal, a release lost to a dialog no longer leaves the next click half reported, and the legacy encoding reports nothing past column 223, as xterm. On macOS, Shift+wheel arrives as a horizontal scroll, so there history can only be scrolled with the scroll bar while a program listens.

Programs that draw their own screen - htop, ncurses menus, and lately
CLIs with clickable options and wheel scrolling - ask the terminal for
mouse events with DEC modes 1000 (presses and releases), 1002 (also
drags) and 1003 (every move), in xterm's legacy encoding or the SGR one
(mode 1006). The terminal ignored the request and kept every click for
its own selection, so such programs could not be clicked on or scrolled.

The canvas now hands presses, releases, moves and the wheel to the
control while a program has asked for them, with the alt and control
keys folded into the button as xterm does. A click the program takes is
the program's alone, as in xterm and GNOME Terminal: the middle-click
does not also paste, the right-click opens no context menu (the menu
key still does), and neither a double-click nor the copy on release
acts on it. The canvas reports it in a listener that runs before every
other and stops the event there. Shift keeps the mouse, the wheel
included, for the terminal, which is the convention every terminal uses
to still allow a selection while a program is listening. Positions are
the program's screen, counted from its first line, not from the top of
the view: with history above the screen the view rarely starts on a
whole line, and a click over the history the user scrolled back to is
the terminal's, not the program's. The legacy encoding reports nothing
past column or row 223, as xterm, rather than bytes it has no room for. A press that went to the
program takes the terminal's selection away and moves the selection
anchor to the click, so a later shift-drag starts from where the user
last clicked rather than from a selection made long before. A release
goes wherever its press went, whatever the keyboard state by then, so
press and release always reach the same side.

This builds on the DEC private mode parsing change (every parameter in
a set/reset), since ncurses turns the mouse on with CSI ? 1006 ; 1000 h.

A reset, which runs before every connection, turns mouse reporting and
SGR mouse encoding off, and nothing is reported while the terminal is
not connected: a program cut off while it listened left the reports on
for the next connection, and a click in between threw from writing to
an output stream that no longer existed. The modes are written by the
reader job and read on the display thread, so they are volatile, as is
application cursor keys, which had the same gap.

MouseReport.mouseReport is public, as the test bundle calls it across
the bundle boundary.
@insjang

insjang commented Nov 6, 2026

Copy link
Copy Markdown
Contributor Author

The one failing check was SeparateVMTests.testExtensionPointType in the Ant UI tests on macOS ("Console is not closed"), which passed on the previous push and on Linux and Windows here; it looks unrelated to this change, and the macOS job is running again. All terminal tests pass.

@insjang

insjang commented Nov 9, 2026

Copy link
Copy Markdown
Contributor Author

@akurtakov, a short status so this one does not get lost among the others:

  • Synchronized output is out of this PR, as you asked. It is ready as a PR of its own, and I will open it once the queue is shorter.
  • The two ESC literals are escaped now.
  • The one failing check is SeparateVMTests.testExtensionPointType in the macOS Ant UI tests, which this PR does not touch (details above).

Could you take another look when you have time? After this one I would suggest #3059 (parser rules) and then #2904 (grapheme clusters). If #2904 is too large to review in one go, I can split it into smaller PRs.

@akurtakov

Copy link
Copy Markdown
Member

I'm a bit overloaded right now, I'll get back to your PRs when time permits. Maybe someone else decides to jump int too .

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants