Skip to content

[Bug] Files view: dragging across line numbers to comment is unreliable (web, desktop, VS Code extension) #5556

Closed

Description

@sogeisetsu

Before submitting

  • I searched existing issues and didn't find this bug
  • This is one bug. Other problems get their own issue.

Where it happens

Web in a browser and the desktop app (Windows) are where I reproduced it. The VS Code extension ships the same Files view from packages/ui, so it has the same gutter, the same handlers and the same behaviour; the fix belongs in the shared UI package so web, desktop and the VS Code webview all get it.

I hit it in the desktop app 2.5.0, and checked the built VS Code extension 2.5.1 (dist/webview/assets) — identical logic.

Steps to reproduce

  1. Open the Files view and open a code file (any .ts/.py works).
  2. Press the mouse on a line number in the gutter and drag down over the next 5-10 line numbers.
  3. Release.

Roughly half the attempts end with a one-line range, and long drags fail more often than short ones. Any drag that drifts a few pixels to the right, into the code area, stops extending at the line where it left the gutter. The same happens in the VS Code extension's Files view.

What I expected

The selected range follows the pointer as far down as I drag, and keeps going (auto-scrolling) when I reach the bottom edge of the editor.

What happened instead

The range freezes as soon as the pointer is no longer over the line-number column, and dragging past the last visible line does nothing because there is no auto-scroll. The same gesture sometimes extends correctly and sometimes does nothing, so comments end up on the wrong line range.

OpenChamber version

Desktop app 2.5.0, VS Code extension 2.5.1

OpenCode version and model/provider (if relevant)

2.0.32

Why it happens (from the shipped bundles)

In Files view, the code editor passes domEventHandlers (mousedown / mouseover / mouseup) to CodeMirror's lineNumbers(). The drag extension is driven only by that mouseover:

  • CodeMirror binds the handlers to the gutter element (src/gutter.ts), so mouseover fires only while the pointer is inside that narrow column. Leaving it — sideways into the code, or out of the editor — ends the extension.
  • The handler requires event.buttons === 1 and the isSelectingRef set by mousedown; there is no setPointerCapture, no document-level pointermove with a clientY -> line mapping, and no edge auto-scroll.
  • Each step also calls setLineSelection + setIsDragging, which changes highlightLines and re-creates the blockWidgets memo (it depends on lineSelection). Both compartments are reconfigured, so the editor re-renders on every line the drag crosses.

I confirmed the same code in the shipped web-dist/assets/FilesView-*.js (desktop 2.5.0) and dist/webview/assets (extension 2.5.1); I have not built from source.

Suggested fix

Track the drag outside the gutter as well: on gutter pointerdown, either capture the pointer or attach a document pointermove that maps clientY to a line (lineBlockAtHeight / posAtCoords), so drifting out of the column keeps extending instead of stopping. Add auto-scroll near the top/bottom edge, recomputing the line per frame. Flip isDragging only at drag start/end and keep the highlight and comment-widget extensions stable during the drag so the editor is not reconfigured on every crossed line.

Workaround that works today, in both the desktop app and the VS Code extension: click the first line number, then Shift+click the last one. That goes through the same lineSelection state with a single mousedown and does not depend on the drag.

Activity

  1. changed the title [-][Bug] Files view: dragging across line numbers to comment is unreliable[/-] [+][Bug] Files view: dragging across line numbers to comment is unreliable (web, desktop, VS Code extension)[/+] on Oct 24, 2026
  2. openchamber-bot commented on Oct 24, 2026

    @openchamber-bot
    Contributor

    For the maintainer: fix-ready — cause traced

    The drag state machine for gutter line selection lives entirely in gutter-bound handlers: mousedown sets isSelectingRef (packages/ui/src/components/views/FilesView.tsx:3681-3730), mouseover extends the range only while event.buttons === 1 (FilesView.tsx:3731-3748), and mouseup ends it (FilesView.tsx:3749-3754). These are handed to CodeMirror's lineNumbers() via lineNumbersConfig.domEventHandlers (FilesView.tsx:3758-3764), which binds them to the gutter element — so mouseover fires only while the pointer is inside the line-number column. Leaving it freezes the range at the last gutter line crossed; a fast drift can cross zero gutter cells, leaving the one-line range from mousedown. There is no setPointerCapture, no document-level move handler with a clientY → line mapping, and no edge auto-scroll, so your two failure modes and the flakiness follow directly. Your analysis is right; nothing in current main changes it.

    Two additions:

    1. Stale drag state on release outside the gutter. The only mouseup handler is gutter-bound (FilesView.tsx:3749), so releasing over the code area never clears isDragging/isSelectingRef; they persist until the next gutter event.
    2. PlanView has the identical pattern (packages/ui/src/components/views/PlanView.tsx:976-1015), so the fix should cover both.

    The per-line reconfiguration claim also checks out: each mouseover calls setLineSelection + setIsDragging (FilesView.tsx:3745-3746); lineSelection feeds highlightLines (FilesView.tsx:5353-5356) and both feed the blockWidgets memo (FilesView.tsx:4078-4100), and CodeMirrorEditor.tsx:503-507 reconfigures both compartments on change — two compartment reconfigurations plus requestMeasure per crossed line (CodeMirrorEditor.tsx:516-519).

    Code path
    1. mousedown on a gutter line: FilesView.tsx:3681 sets isSelectingRef.current = true, selectionStartRef.current = lineNumber, setIsDragging(true), and setLineSelection({start: n, end: n}) (3717-3726).
    2. Drag moves over gutter cells: mouseover (FilesView.tsx:3731) checks event.buttons === 1 and the ref, then setLineSelection (3743-3746). CodeMirror invokes gutter domEventHandlers only for events on the gutter DOM, so any mouseover over the code area never reaches this handler.
    3. Pointer leaves the gutter: no handler fires → range frozen; no auto-scroll exists anywhere in this handler set.
    4. Release outside the gutter: gutter mouseup (3749) never runs → isDragging stays true.
    5. React re-render from setLineSelection: highlightLines prop changes (5353) and blockWidgets memo identity changes (4100); CodeMirrorEditor.tsx:503-507 dispatches compartment reconfigurations for both on every crossed line.

    Mechanism is confirmed by source reading; it matches your shipped-bundle analysis, but has not been runtime-reproduced against your specific Windows 2.5.0 build.

    The suggested fix shape (gutter pointerdown → pointer capture or document pointermove with posAtCoords, edge auto-scroll, isDragging flipped only at drag start/end) fits what the code needs; the Shift+click path you found is unaffected.

  3. added
    bugSomething isn't working
    root-cause:foundBot traced a concrete code-level cause (not yet confirmed by the reporter)
    on Oct 24, 2026
  4. added a commit that references this issue on Oct 25, 2026
    9fe0a46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

bugSomething isn't workingroot-cause:foundBot traced a concrete code-level cause (not yet confirmed by the reporter)

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions