@aurigax-ai/ghostty-web 0.3.5 → 0.3.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -881,6 +881,8 @@ export class InputHandler {
881
881
 
882
882
  const button = event.button;
883
883
 
884
+ if (!(this.mouseButtonsPressed & (1 << button))) return;
885
+
884
886
  // Clear pressed button
885
887
  this.mouseButtonsPressed &= ~(1 << button);
886
888
 
package/lib/renderer.ts CHANGED
@@ -268,8 +268,6 @@ export abstract class TerminalRenderer {
268
268
  private readonly highlightRows = new Set<number>();
269
269
  protected highlightColors: SearchHighlightColors = { match: '#5c6266', active: '#538bb5' };
270
270
 
271
- protected hoveredHyperlinkId = 0;
272
- private previousHoveredHyperlinkId = 0;
273
271
  protected hoveredLinkRange: LinkRange | null = null;
274
272
  private previousHoveredLinkRange: LinkRange | null = null;
275
273
 
@@ -385,22 +383,6 @@ export abstract class TerminalRenderer {
385
383
  };
386
384
 
387
385
  const hyperlinkRows = new Set<number>();
388
- if (this.hoveredHyperlinkId !== this.previousHoveredHyperlinkId) {
389
- for (let y = 0; y < dims.rows; y++) {
390
- const line = lineAt(y);
391
- if (!line) continue;
392
- for (const cell of line) {
393
- if (
394
- cell.hyperlink_id === this.hoveredHyperlinkId ||
395
- cell.hyperlink_id === this.previousHoveredHyperlinkId
396
- ) {
397
- hyperlinkRows.add(y);
398
- break;
399
- }
400
- }
401
- }
402
- this.previousHoveredHyperlinkId = this.hoveredHyperlinkId;
403
- }
404
386
  if (!sameRange(this.hoveredLinkRange, this.previousHoveredLinkRange)) {
405
387
  for (const range of [this.previousHoveredLinkRange, this.hoveredLinkRange]) {
406
388
  if (!range) continue;
@@ -511,9 +493,8 @@ export abstract class TerminalRenderer {
511
493
  /** Called when the search highlight colors change. */
512
494
  protected searchColorsChanged(): void {}
513
495
 
514
- /** Whether the cell has a hovered link under it (OSC 8 id or a detected URL range). */
515
- protected linkHovered(cell: GhosttyCell, x: number, y: number): boolean {
516
- if (cell.hyperlink_id > 0 && cell.hyperlink_id === this.hoveredHyperlinkId) return true;
496
+ /** Whether the cell has a hovered link under it (OSC 8 or detected URL range). */
497
+ protected linkHovered(x: number, y: number): boolean {
517
498
  const range = this.hoveredLinkRange;
518
499
  if (!range) return false;
519
500
  return (
@@ -676,14 +657,6 @@ export abstract class TerminalRenderer {
676
657
  this.selectionManager = manager;
677
658
  }
678
659
 
679
- public setHoveredHyperlinkId(hyperlinkId: number): void {
680
- this.hoveredHyperlinkId = hyperlinkId;
681
- }
682
-
683
- public getHoveredHyperlinkId(): number {
684
- return this.hoveredHyperlinkId;
685
- }
686
-
687
660
  /** Set the hovered range of a detected URL, or null to clear it. */
688
661
  public setHoveredLinkRange(range: LinkRange | null): void {
689
662
  this.hoveredLinkRange = range;
@@ -1006,7 +979,7 @@ export class CanvasRenderer extends TerminalRenderer {
1006
979
  private renderDecorations(cell: GhosttyCell, x: number, y: number, color: string): void {
1007
980
  const underline = cell.flags & CellFlags.UNDERLINE;
1008
981
  const strike = cell.flags & CellFlags.STRIKETHROUGH;
1009
- const link = (cell.hyperlink_id > 0 || this.hoveredLinkRange) && this.linkHovered(cell, x, y);
982
+ const link = this.hoveredLinkRange && this.linkHovered(x, y);
1010
983
  if (!underline && !strike && !link) return;
1011
984
  const cellX = x * this.metrics.width;
1012
985
  const cellY = y * this.metrics.height;
package/lib/terminal.ts CHANGED
@@ -660,10 +660,8 @@ export class Terminal implements ITerminalCore {
660
660
  /** Disposes the current renderer and draws with `renderer` from now on, in its state. */
661
661
  private installRenderer(renderer: TerminalRenderer): void {
662
662
  const old = this.renderer!;
663
- const hoveredLink = old.getHoveredHyperlinkId();
664
663
  old.dispose();
665
664
  renderer.onNeedsFrame = () => this.requestFrame();
666
- renderer.setHoveredHyperlinkId(hoveredLink);
667
665
  renderer.setFocused(this.focused);
668
666
  renderer.setSearchHighlights(this.searchHighlights.list, this.searchHighlights.colors);
669
667
  if (this.selectionManager) {
@@ -1258,7 +1256,7 @@ export class Terminal implements ITerminalCore {
1258
1256
  const absDistance = Math.abs(distance);
1259
1257
 
1260
1258
  // If very close, snap to target
1261
- if (absDistance < 0.01) {
1259
+ if (absDistance < 0.01 || duration <= 0) {
1262
1260
  this.viewportY = this.targetViewportY;
1263
1261
  this.fireScroll();
1264
1262
 
@@ -1545,47 +1543,7 @@ export class Terminal implements ITerminalCore {
1545
1543
  const x = Math.floor((e.clientX - rect.left) / this.renderer.charWidth);
1546
1544
  const y = Math.floor((e.clientY - rect.top) / this.renderer.charHeight);
1547
1545
 
1548
- // Get hyperlink_id directly from the cell at this position
1549
- // Must account for viewportY (scrollback position)
1550
- const viewportRow = y; // Row in the viewport (0 to rows-1)
1551
- let hyperlinkId = 0;
1552
-
1553
- // When scrolled, fetch from scrollback or screen based on position
1554
- // NOTE: viewportY may be fractional during smooth scrolling. The renderer
1555
- // uses Math.floor(viewportY) when mapping viewport rows to scrollback vs
1556
- // screen; we mirror that logic here so link hit-testing matches what the
1557
- // user sees on screen.
1558
- let line: GhosttyCell[] | null = null;
1559
- const rawViewportY = this.getViewportY();
1560
- const viewportY = Math.max(0, Math.floor(rawViewportY));
1561
- if (viewportY > 0) {
1562
- const scrollbackLength = this.wasmTerm.getScrollbackLength();
1563
- if (viewportRow < viewportY) {
1564
- // Mouse is over scrollback content
1565
- const scrollbackOffset = scrollbackLength - viewportY + viewportRow;
1566
- line = this.wasmTerm.getScrollbackLine(scrollbackOffset);
1567
- } else {
1568
- // Mouse is over screen content (bottom part of viewport)
1569
- const screenRow = viewportRow - viewportY;
1570
- line = this.wasmTerm.getLine(screenRow);
1571
- }
1572
- } else {
1573
- // At bottom - just use screen buffer
1574
- line = this.wasmTerm.getLine(viewportRow);
1575
- }
1576
-
1577
- if (line && x >= 0 && x < line.length) {
1578
- hyperlinkId = line[x].hyperlink_id;
1579
- }
1580
-
1581
- // Update renderer for underline rendering
1582
- const previousHyperlinkId = (this.renderer as any).hoveredHyperlinkId || 0;
1583
- if (hyperlinkId !== previousHyperlinkId) {
1584
- this.renderer.setHoveredHyperlinkId(hyperlinkId);
1585
-
1586
- // The 60fps render loop will pick up the change automatically
1587
- // No need to force a render - this keeps performance smooth
1588
- }
1546
+ const viewportRow = y;
1589
1547
 
1590
1548
  // Check if there's a link at this position (for click handling and cursor)
1591
1549
  // Buffer API expects absolute buffer coordinates (including scrollback)
@@ -1678,12 +1636,6 @@ export class Terminal implements ITerminalCore {
1678
1636
  this.wake();
1679
1637
  // Clear hyperlink underline
1680
1638
  if (this.renderer && this.wasmTerm) {
1681
- const previousHyperlinkId = (this.renderer as any).hoveredHyperlinkId || 0;
1682
- if (previousHyperlinkId > 0) {
1683
- this.renderer.setHoveredHyperlinkId(0);
1684
-
1685
- // The 60fps render loop will pick up the change automatically
1686
- }
1687
1639
  // Clear regex link underline
1688
1640
  this.renderer.setHoveredLinkRange(null);
1689
1641
  }
@@ -610,7 +610,7 @@ export class WebglRenderer extends TerminalRenderer {
610
610
  }
611
611
  }
612
612
 
613
- const link = (cell.hyperlink_id > 0 || this.hoveredLinkRange) && this.linkHovered(cell, x, y);
613
+ const link = this.hoveredLinkRange && this.linkHovered(x, y);
614
614
  if (link || cell.flags & CellFlags.UNDERLINE) {
615
615
  rects[deco1] = left;
616
616
  rects[deco1 + 1] = underlineY;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aurigax-ai/ghostty-web",
3
- "version": "0.3.5",
3
+ "version": "0.3.7",
4
4
  "description": "Ghostty's terminal engine (libghostty-vt) in the browser: WebAssembly build, an xterm.js-shaped API and WebGL and canvas renderers. A hard fork of coder/ghostty-web.",
5
5
  "type": "module",
6
6
  "main": "./lib/index.ts",