Conversation
- Add SelectionManager class for mouse-based text selection * Click and drag to select text * Double-click to select word * Auto-copy to clipboard on selection * Visual selection overlay with semi-transparent highlight - Integrate SelectionManager into Terminal class * Add getSelection(), hasSelection(), clearSelection(), selectAll() API * Add onSelectionChange event * Auto-clear selection when writing new data - Update CanvasRenderer to draw selection overlay * Add setSelectionManager() and getCanvas() methods * Render semi-transparent selection highlight - Update library exports to include SelectionManager - Clean up demo placeholder selection code * Remove broken enableTextSelection() function * Document that selection is now built-in - Add workflow best practice to AGENTS.md * Always pull from main before starting work Features: - xterm.js-compatible selection API - Mouse drag selection with coordinate conversion - Word boundary detection for double-click - Wide character support (CJK, emoji) - Multi-line selection with newlines - Clipboard integration - Selection clears on terminal write Tests: 88 pass (including 2 new selection tests) Type check: ✅ passes
- Force re-render of selection-affected lines - Add right-click context menu handler for copy - Add debug logging to track selection rendering - Create test-selection.html for manual testing Issues being debugged: - Selection appears opaque instead of semi-transparent - Selection doesn't clear properly - Right-click shows 'Copy Image' instead of text
ROOT CAUSE: The 60fps render loop was drawing the selection overlay every frame. With alpha=0.5, drawing 6+ times makes it opaque. FIX: - Only redraw selection when selection-affected lines are being redrawn - Mark selection lines as needing redraw (so they clear old overlay) - Draw selection overlay once after lines are cleared/redrawn - Remove excessive debug logging This ensures selection is drawn exactly once per frame, maintaining the semi-transparent effect. Testing: Selection should now be semi-transparent blue overlay
Issues Fixed: 1. Selection highlight persists after clicking elsewhere - Now tracks previousSelection coordinates - Renderer redraws those lines to clear old overlay - Selection clears immediately on mousedown 2. No feedback for clipboard operations - Added console.log for successful copy - Added error messages with helpful hints - Shows if Clipboard API is unavailable 3. Improved mousedown behavior - Always clears selection on new click - Starts fresh selection from click point Changes: - Track previousSelection in SelectionManager - Add getPreviousSelectionCoords() and clearPreviousSelection() methods - Renderer checks previousSelection and redraws those lines - Enhanced copyToClipboard() with success/error logging - Simplified mousedown handler Testing: Selection should now clear when clicking elsewhere
Issue: Clipboard API requires HTTPS or specifically 'localhost' hostname.
Custom domains like 'mux.coder' are not considered secure contexts even
when they resolve to localhost.
Solution:
- Try modern navigator.clipboard API first (works on HTTPS/localhost)
- Fall back to document.execCommand('copy') for non-secure contexts
- execCommand works on custom domains and older browsers
- Provide clear console feedback about which method was used
This uses the "textarea trick":
1. Create hidden textarea with selected text
2. Select its content
3. Call document.execCommand('copy')
4. Remove textarea
Result: Copy works on mux.coder and similar custom domains.
Testing: Should now see '✅ Copied to clipboard (fallback)' message
and be able to paste the selected text.
CRITICAL BUG: Keyboard input stopped working after adding selection. Root Cause: - InputHandler attaches to container element (has tabindex, receives keys) - SelectionManager adds mousedown listener to canvas element - Clicks on canvas don't propagate focus to container - Container loses focus → no keyboard events → no typing Solution: - On mousedown, explicitly focus the parent container - This ensures keyboard events continue to work - Selection still works as expected Testing: - Click on terminal → should be able to type - Select text → should still be able to type afterward - Focus is maintained on the container at all times
Issue 1 - Can't type after copy: - copyToClipboardFallback creates textarea and calls textarea.focus() - This steals focus from terminal container - User can't type because container doesn't have focus anymore Fix: - Save document.activeElement before copy - Restore focus after copy completes - Works even if copy fails (try/catch) Issue 2 - Slow input: - Selection lines were being redrawn EVERY frame (60fps) - Even when selection was static and not changing - Caused noticeable input lag Fix: - Only redraw selection lines when actively selecting (mouse is down) - Or when clearing previous selection - When typing, terminal.write() clears selection anyway - This prevents unnecessary redraws during normal typing Performance: - Before: 24 lines redrawn every frame with selectAll() - After: 0 lines redrawn when selection is static - Result: Input is fast again! Testing: Input should be responsive, paste should work repeatedly
Problem: When dragging to select text and releasing mouse outside canvas bounds, the selection would continue on mousemove because the canvas mouseup event never fired. Solution: Move mouseup listener from canvas to document to catch releases anywhere on the page. This is the standard pattern for drag operations. Changes: - Move mouseup event listener to document scope - Add mouseleave handler for better debugging - Add console.log statements to track isSelecting state - Store boundMouseUpHandler for proper cleanup in dispose() - Update AGENTS.md to avoid committing summary markdown files Test: Drag selection and release mouse outside terminal bounds - selection should stop properly instead of continuing on hover.
Remove agent-generated files that shouldn't be tracked: - DEBUG_SELECTION.md - IMPLEMENTATION_SUMMARY.md - SELECTION_TESTING.md - test-selection.html - test-selection-alpha.html These were used for debugging during development.
sreya
added a commit
that referenced
this pull request
Nov 13, 2025
* feat: implement text selection for terminal
- Add SelectionManager class for mouse-based text selection
* Click and drag to select text
* Double-click to select word
* Auto-copy to clipboard on selection
* Visual selection overlay with semi-transparent highlight
- Integrate SelectionManager into Terminal class
* Add getSelection(), hasSelection(), clearSelection(), selectAll() API
* Add onSelectionChange event
* Auto-clear selection when writing new data
- Update CanvasRenderer to draw selection overlay
* Add setSelectionManager() and getCanvas() methods
* Render semi-transparent selection highlight
Testing: Selection should now be semi-transparent blue overlay
* fix: selection clearing and clipboard feedback
Issues Fixed:
1. Selection highlight persists after clicking elsewhere
- Now tracks previousSelection coordinates
- Renderer redraws those lines to clear old overlay
- Selection clears immediately on mousedown
2. No feedback for clipboard operations
- Added console.log for successful copy
- Added error messages with helpful hints
- Shows if Clipboard API is unavailable
3. Improved mousedown behavior
- Always clears selection on new click
- Starts fresh selection from click point
Changes:
- Track previousSelection in SelectionManager
- Add getPreviousSelectionCoords() and clearPreviousSelection() methods
- Renderer checks previousSelection and redraws those lines
- Enhanced copyToClipboard() with success/error logging
- Simplified mousedown handler
Testing: Selection should now clear when clicking elsewhere
* fix: add clipboard fallback for non-secure contexts
Issue: Clipboard API requires HTTPS or specifically 'localhost' hostname.
Custom domains like 'mux.coder' are not considered secure contexts even
when they resolve to localhost.
Solution:
- Try modern navigator.clipboard API first (works on HTTPS/localhost)
- Fall back to document.execCommand('copy') for non-secure contexts
- execCommand works on custom domains and older browsers
- Provide clear console feedback about which method was used
This uses the "textarea trick":
1. Create hidden textarea with selected text
2. Select its content
3. Call document.execCommand('copy')
4. Remove textarea
Result: Copy works on mux.coder and similar custom domains.
Testing: Should now see '✅ Copied to clipboard (fallback)' message
and be able to paste the selected text.
* fix: restore keyboard input by focusing container on mousedown
CRITICAL BUG: Keyboard input stopped working after adding selection.
Root Cause:
- InputHandler attaches to container element (has tabindex, receives keys)
- SelectionManager adds mousedown listener to canvas element
- Clicks on canvas don't propagate focus to container
- Container loses focus → no keyboard events → no typing
Solution:
- On mousedown, explicitly focus the parent container
- This ensures keyboard events continue to work
- Selection still works as expected
Testing:
- Click on terminal → should be able to type
- Select text → should still be able to type afterward
- Focus is maintained on the container at all times
* fix: restore focus after clipboard copy and optimize selection rendering
Issue 1 - Can't type after copy:
- copyToClipboardFallback creates textarea and calls textarea.focus()
- This steals focus from terminal container
- User can't type because container doesn't have focus anymore
Fix:
- Save document.activeElement before copy
- Restore focus after copy completes
- Works even if copy fails (try/catch)
Issue 2 - Slow input:
- Selection lines were being redrawn EVERY frame (60fps)
- Even when selection was static and not changing
- Caused noticeable input lag
Fix:
- Only redraw selection lines when actively selecting (mouse is down)
- Or when clearing previous selection
- When typing, terminal.write() clears selection anyway
- This prevents unnecessary redraws during normal typing
Performance:
- Before: 24 lines redrawn every frame with selectAll()
- After: 0 lines redrawn when selection is static
- Result: Input is fast again!
Testing: Input should be responsive, paste should work repeatedly
* Fix: Selection continues after mouse release outside canvas
Problem: When dragging to select text and releasing mouse outside canvas
bounds, the selection would continue on mousemove because the canvas
mouseup event never fired.
Solution: Move mouseup listener from canvas to document to catch releases
anywhere on the page. This is the standard pattern for drag operations.
Changes:
- Move mouseup event listener to document scope
- Add mouseleave handler for better debugging
- Add console.log statements to track isSelecting state
- Store boundMouseUpHandler for proper cleanup in dispose()
- Update AGENTS.md to avoid committing summary markdown files
Test: Drag selection and release mouse outside terminal bounds - selection
should stop properly instead of continuing on hover.
* chore: remove temporary test and doc files
Remove agent-generated files that shouldn't be tracked:
- DEBUG_SELECTION.md
- IMPLEMENTATION_SUMMARY.md
- SELECTION_TESTING.md
- test-selection.html
- test-selection-alpha.html
These were used for debugging during development.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.