restty 0.1.16 → 0.1.17
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.
- package/dist/app/atlas-builder.d.ts +38 -0
- package/dist/app/font-sources.d.ts +2 -0
- package/dist/app/index.js +234 -90
- package/dist/app/pane-app-manager.d.ts +43 -0
- package/dist/app/panes-context-menu.d.ts +10 -0
- package/dist/app/panes-styles.d.ts +5 -0
- package/dist/app/panes-types.d.ts +89 -0
- package/dist/app/panes.d.ts +10 -0
- package/dist/app/restty.d.ts +20 -0
- package/dist/app/session.d.ts +6 -0
- package/dist/app/types.d.ts +123 -0
- package/dist/fonts/index.js +2 -1
- package/dist/fonts/manager.d.ts +25 -0
- package/dist/fonts/nerd-constraints.d.ts +4 -0
- package/dist/fonts/nerd-ranges.d.ts +2 -0
- package/dist/fonts/types.d.ts +51 -0
- package/dist/grid/grid.d.ts +22 -0
- package/dist/grid/types.d.ts +32 -0
- package/dist/ime/ime.d.ts +13 -0
- package/dist/ime/types.d.ts +8 -0
- package/dist/index.js +234 -90
- package/dist/input/ansi.d.ts +3 -0
- package/dist/input/index.js +5 -1
- package/dist/input/mouse.d.ts +10 -0
- package/dist/input/output.d.ts +11 -0
- package/dist/input/types.d.ts +7 -0
- package/dist/internal.js +234 -90
- package/dist/pty/kitty-media.d.ts +3 -0
- package/dist/pty/pty.d.ts +11 -0
- package/dist/pty/types.d.ts +49 -0
- package/dist/renderer/box-drawing-map.d.ts +4 -0
- package/dist/renderer/index.js +145 -42
- package/dist/renderer/shaders.d.ts +7 -0
- package/dist/renderer/shapes.d.ts +43 -0
- package/dist/renderer/types.d.ts +43 -0
- package/dist/renderer/webgpu.d.ts +11 -0
- package/dist/selection/selection.d.ts +24 -0
- package/dist/selection/types.d.ts +13 -0
- package/dist/theme/catalog.d.ts +5 -0
- package/dist/theme/ghostty.d.ts +18 -0
- package/dist/wasm/embedded.d.ts +1 -0
- package/dist/wasm/runtime.d.ts +29 -0
- package/package.json +1 -1
|
@@ -1,9 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Metadata for constrained glyph rendering.
|
|
3
|
+
* - cp: Unicode code point
|
|
4
|
+
* - constraintWidth: target cell width constraint
|
|
5
|
+
* - variable: whether glyph can render at multiple widths
|
|
6
|
+
* - widths: set of all required cell widths for this glyph
|
|
7
|
+
*/
|
|
1
8
|
export type GlyphConstraintMeta = {
|
|
2
9
|
cp: number;
|
|
3
10
|
constraintWidth: number;
|
|
4
11
|
variable?: boolean;
|
|
5
12
|
widths?: Set<number>;
|
|
6
13
|
};
|
|
14
|
+
/**
|
|
15
|
+
* Context for constraint-based atlas building, primarily for Nerd Fonts symbol alignment.
|
|
16
|
+
* - cellW: cell width in pixels
|
|
17
|
+
* - cellH: cell height in pixels
|
|
18
|
+
* - yPad: vertical padding
|
|
19
|
+
* - baselineOffset: baseline offset adjustment
|
|
20
|
+
* - baselineAdjust: additional baseline adjustment
|
|
21
|
+
* - fontScale: scale factor for font rendering
|
|
22
|
+
* - nerdMetrics: Nerd Fonts specific layout metrics
|
|
23
|
+
* - fontEntry: reference to font entry object
|
|
24
|
+
*/
|
|
7
25
|
export type AtlasConstraintContext = {
|
|
8
26
|
cellW: number;
|
|
9
27
|
cellH: number;
|
|
@@ -60,6 +78,17 @@ type BuildAtlasDeps = {
|
|
|
60
78
|
atlasScale: number;
|
|
61
79
|
}) => boolean;
|
|
62
80
|
};
|
|
81
|
+
/**
|
|
82
|
+
* Parameters for font atlas building.
|
|
83
|
+
* - entry: font entry containing the font object and cached atlas
|
|
84
|
+
* - neededGlyphIds: set of glyph IDs required in the atlas
|
|
85
|
+
* - glyphMeta: optional constraint metadata for symbol font glyphs
|
|
86
|
+
* - fontSizePx: base font size in pixels
|
|
87
|
+
* - atlasScale: scaling factor for high-DPI rendering
|
|
88
|
+
* - fontIndex: index in the font fallback chain (0 = primary font)
|
|
89
|
+
* - constraintContext: optional constraint context for symbol alignment
|
|
90
|
+
* - deps: external dependencies for atlas building
|
|
91
|
+
*/
|
|
63
92
|
export type BuildFontAtlasParams = {
|
|
64
93
|
entry: any;
|
|
65
94
|
neededGlyphIds: Set<number>;
|
|
@@ -70,6 +99,14 @@ export type BuildFontAtlasParams = {
|
|
|
70
99
|
constraintContext?: AtlasConstraintContext | null;
|
|
71
100
|
deps: BuildAtlasDeps;
|
|
72
101
|
};
|
|
102
|
+
/**
|
|
103
|
+
* Result from font atlas building.
|
|
104
|
+
* - rebuilt: true if a new atlas was generated
|
|
105
|
+
* - atlas: the atlas object containing glyph metrics and bitmap
|
|
106
|
+
* - rgba: RGBA pixel data ready for WebGL upload
|
|
107
|
+
* - colorGlyphs: set of glyph IDs that are color emoji
|
|
108
|
+
* - preferNearest: whether to use nearest-neighbor texture filtering
|
|
109
|
+
*/
|
|
73
110
|
export type BuildFontAtlasResult = {
|
|
74
111
|
rebuilt: boolean;
|
|
75
112
|
atlas: any | null;
|
|
@@ -77,5 +114,6 @@ export type BuildFontAtlasResult = {
|
|
|
77
114
|
colorGlyphs?: Set<number>;
|
|
78
115
|
preferNearest: boolean;
|
|
79
116
|
};
|
|
117
|
+
/** Builds or reuses a font atlas, detecting when rebuild is needed based on glyph requirements, size changes, or constraint updates. */
|
|
80
118
|
export declare function buildFontAtlasIfNeeded(params: BuildFontAtlasParams): BuildFontAtlasResult;
|
|
81
119
|
export {};
|
|
@@ -1,3 +1,5 @@
|
|
|
1
1
|
import type { ResttyFontPreset, ResttyFontSource } from "./types";
|
|
2
|
+
/** Default font fallback chain with JetBrains Mono, Nerd Fonts symbols, Noto symbols, color emoji, black emoji, and CJK support. */
|
|
2
3
|
export declare const DEFAULT_FONT_SOURCES: ResttyFontSource[];
|
|
4
|
+
/** Validates user-provided font sources or returns defaults based on preset (none returns empty array, otherwise default CDN fonts). */
|
|
3
5
|
export declare function normalizeFontSources(sources: ResttyFontSource[] | undefined, preset: ResttyFontPreset | undefined): ResttyFontSource[];
|
package/dist/app/index.js
CHANGED
|
@@ -148,11 +148,14 @@ function isPowerline(cp) {
|
|
|
148
148
|
function isBraille(cp) {
|
|
149
149
|
return cp >= 10240 && cp <= 10495;
|
|
150
150
|
}
|
|
151
|
+
function isTransportControlSymbol(cp) {
|
|
152
|
+
return cp >= 9193 && cp <= 9210;
|
|
153
|
+
}
|
|
151
154
|
function isGraphicsElement(cp) {
|
|
152
155
|
return isBoxDrawing(cp) || isBlockElement(cp) || isLegacyComputing(cp) || isPowerline(cp);
|
|
153
156
|
}
|
|
154
157
|
function isSymbolCp(cp) {
|
|
155
|
-
return isPrivateUse(cp) || isGraphicsElement(cp);
|
|
158
|
+
return isPrivateUse(cp) || isGraphicsElement(cp) || isTransportControlSymbol(cp);
|
|
156
159
|
}
|
|
157
160
|
function applyAlpha(color, alpha) {
|
|
158
161
|
return [color[0], color[1], color[2], color[3] * alpha];
|
|
@@ -303,8 +306,7 @@ function drawBlockElement(cp, x, y, cellW, cellH, color, out) {
|
|
|
303
306
|
function drawBoxDrawing(cp, x, y, cellW, cellH, color, out) {
|
|
304
307
|
const spec = BOX_LINE_MAP.get(cp);
|
|
305
308
|
if (!spec) {
|
|
306
|
-
const
|
|
307
|
-
const light2 = Math.max(1, Math.round(minDim2 * 0.08));
|
|
309
|
+
const light2 = Math.max(1, Math.round(cellH * 0.08));
|
|
308
310
|
const heavy2 = Math.max(light2 + 1, Math.round(light2 * 1.8));
|
|
309
311
|
const dashedH = (count, thickness) => {
|
|
310
312
|
const gap2 = Math.max(1, Math.round(thickness));
|
|
@@ -338,39 +340,146 @@ function drawBoxDrawing(cp, x, y, cellW, cellH, color, out) {
|
|
|
338
340
|
pushRectBox(out, px - thickness * 0.5, py - thickness * 0.5, thickness, thickness, color);
|
|
339
341
|
}
|
|
340
342
|
};
|
|
341
|
-
const
|
|
342
|
-
const thickness = light2;
|
|
343
|
-
const
|
|
344
|
-
const cx2 = x + cellW * 0.5;
|
|
345
|
-
const cy2 = y + cellH * 0.5;
|
|
346
|
-
const r = Math.min(cellW, cellH) * 0.5;
|
|
347
|
-
const steps = Math.max(24, Math.round(r * 4));
|
|
343
|
+
const drawRoundedCorner = (cornerCp) => {
|
|
344
|
+
const thickness = Math.max(1, Math.round(light2));
|
|
345
|
+
const half = thickness * 0.5;
|
|
348
346
|
const s = 0.25;
|
|
349
|
-
const
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
347
|
+
const cx2 = x + Math.floor((cellW - thickness) * 0.5) + half;
|
|
348
|
+
const cy2 = y + Math.floor((cellH - thickness) * 0.5) + half;
|
|
349
|
+
const r = Math.min(cellW, cellH) * 0.5;
|
|
350
|
+
const p0 = { x: cx2, y };
|
|
351
|
+
const p1 = { x: cx2, y: cy2 - r };
|
|
352
|
+
const c1 = { x: cx2, y: cy2 - s * r };
|
|
353
|
+
const c2 = { x: cx2, y: cy2 };
|
|
354
|
+
const p2 = { x: cx2, y: cy2 };
|
|
355
|
+
const p3 = { x: cx2, y: cy2 };
|
|
356
|
+
let p4 = { x: x + cellW, y: cy2 };
|
|
357
|
+
switch (cornerCp) {
|
|
358
|
+
case 9581:
|
|
359
|
+
p0.y = y + cellH;
|
|
360
|
+
p1.y = cy2 + r;
|
|
361
|
+
c1.y = cy2 + s * r;
|
|
362
|
+
c2.x = cx2 + s * r;
|
|
363
|
+
p2.x = cx2 + r;
|
|
364
|
+
p3.x = cx2 + r;
|
|
365
|
+
p4 = { x: x + cellW, y: cy2 };
|
|
366
|
+
break;
|
|
367
|
+
case 9582:
|
|
368
|
+
p0.y = y + cellH;
|
|
369
|
+
p1.y = cy2 + r;
|
|
370
|
+
c1.y = cy2 + s * r;
|
|
371
|
+
c2.x = cx2 - s * r;
|
|
372
|
+
p2.x = cx2 - r;
|
|
373
|
+
p3.x = cx2 - r;
|
|
374
|
+
p4 = { x, y: cy2 };
|
|
375
|
+
break;
|
|
376
|
+
case 9583:
|
|
377
|
+
c2.x = cx2 - s * r;
|
|
378
|
+
p2.x = cx2 - r;
|
|
379
|
+
p3.x = cx2 - r;
|
|
380
|
+
p4 = { x, y: cy2 };
|
|
381
|
+
break;
|
|
382
|
+
case 9584:
|
|
383
|
+
c2.x = cx2 + s * r;
|
|
384
|
+
p2.x = cx2 + r;
|
|
385
|
+
p3.x = cx2 + r;
|
|
386
|
+
p4 = { x: x + cellW, y: cy2 };
|
|
387
|
+
break;
|
|
388
|
+
}
|
|
389
|
+
const segments = [];
|
|
390
|
+
const addSegment = (a, b) => {
|
|
391
|
+
const dx = b.x - a.x;
|
|
392
|
+
const dy = b.y - a.y;
|
|
393
|
+
const len = Math.hypot(dx, dy);
|
|
394
|
+
if (len <= 0.000001)
|
|
395
|
+
return;
|
|
396
|
+
const ux = dx / len;
|
|
397
|
+
const uy = dy / len;
|
|
398
|
+
segments.push({ ax: a.x, ay: a.y, ux, uy, nx: -uy, ny: ux, len });
|
|
399
|
+
};
|
|
400
|
+
const cubicPoint = (a, b, c, d, t) => {
|
|
401
|
+
const mt = 1 - t;
|
|
402
|
+
const mt2 = mt * mt;
|
|
403
|
+
const t2 = t * t;
|
|
404
|
+
return {
|
|
405
|
+
x: mt2 * mt * a.x + 3 * mt2 * t * b.x + 3 * mt * t2 * c.x + t2 * t * d.x,
|
|
406
|
+
y: mt2 * mt * a.y + 3 * mt2 * t * b.y + 3 * mt * t2 * c.y + t2 * t * d.y
|
|
407
|
+
};
|
|
408
|
+
};
|
|
409
|
+
const steps = Math.max(10, Math.round(Math.max(cellW, cellH) * 1.5));
|
|
410
|
+
const curvePoints = [];
|
|
411
|
+
for (let i = 0;i <= steps; i += 1) {
|
|
412
|
+
const t = i / steps;
|
|
413
|
+
curvePoints.push(cubicPoint(p1, c1, c2, p2, t));
|
|
414
|
+
}
|
|
415
|
+
addSegment(p0, p1);
|
|
416
|
+
for (let i = 1;i < curvePoints.length; i += 1) {
|
|
417
|
+
addSegment(curvePoints[i - 1], curvePoints[i]);
|
|
418
|
+
}
|
|
419
|
+
addSegment(p3, p4);
|
|
420
|
+
const minX = Math.max(Math.floor(x), Math.floor(Math.min(p0.x, p4.x, cx2 - r) - half - 1));
|
|
421
|
+
const maxX = Math.min(Math.ceil(x + cellW) - 1, Math.ceil(Math.max(p0.x, p4.x, cx2 + r) + half + 1));
|
|
422
|
+
const minY = Math.max(Math.floor(y), Math.floor(Math.min(p0.y, p4.y, cy2 - r) - half - 1));
|
|
423
|
+
const maxY = Math.min(Math.ceil(y + cellH) - 1, Math.ceil(Math.max(p0.y, p4.y, cy2 + r) + half + 1));
|
|
424
|
+
if (maxX < minX || maxY < minY)
|
|
425
|
+
return;
|
|
426
|
+
const antiAlias = Math.min(cellW, cellH) >= 22;
|
|
427
|
+
const sampleOffsets = antiAlias ? [
|
|
428
|
+
[0.25, 0.25],
|
|
429
|
+
[0.75, 0.25],
|
|
430
|
+
[0.25, 0.75],
|
|
431
|
+
[0.75, 0.75]
|
|
432
|
+
] : [[0.5, 0.5]];
|
|
433
|
+
const sampleInsideStroke = (sx, sy) => {
|
|
434
|
+
for (const seg of segments) {
|
|
435
|
+
const rx = sx - seg.ax;
|
|
436
|
+
const ry = sy - seg.ay;
|
|
437
|
+
const along = rx * seg.ux + ry * seg.uy;
|
|
438
|
+
if (along < 0 || along > seg.len)
|
|
439
|
+
continue;
|
|
440
|
+
const perp = Math.abs(rx * seg.nx + ry * seg.ny);
|
|
441
|
+
if (perp <= half + 0.000001)
|
|
442
|
+
return true;
|
|
356
443
|
}
|
|
444
|
+
return false;
|
|
357
445
|
};
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
446
|
+
for (let py = minY;py <= maxY; py += 1) {
|
|
447
|
+
let runX = -1;
|
|
448
|
+
let runCoverage = 0;
|
|
449
|
+
for (let px = minX;px <= maxX; px += 1) {
|
|
450
|
+
let coverage = 0;
|
|
451
|
+
for (const [ox, oy] of sampleOffsets) {
|
|
452
|
+
if (sampleInsideStroke(px + ox, py + oy))
|
|
453
|
+
coverage += 1;
|
|
454
|
+
}
|
|
455
|
+
if (coverage > 0 && runX < 0) {
|
|
456
|
+
runX = px;
|
|
457
|
+
runCoverage = coverage;
|
|
458
|
+
continue;
|
|
459
|
+
}
|
|
460
|
+
if (coverage > 0 && coverage === runCoverage)
|
|
461
|
+
continue;
|
|
462
|
+
if (runX >= 0) {
|
|
463
|
+
const alphaColor = [
|
|
464
|
+
color[0],
|
|
465
|
+
color[1],
|
|
466
|
+
color[2],
|
|
467
|
+
color[3] * (runCoverage / sampleOffsets.length)
|
|
468
|
+
];
|
|
469
|
+
pushRectBox(out, runX, py, px - runX, 1, alphaColor);
|
|
470
|
+
runX = coverage > 0 ? px : -1;
|
|
471
|
+
runCoverage = coverage;
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
if (runX >= 0) {
|
|
475
|
+
const alphaColor = [
|
|
476
|
+
color[0],
|
|
477
|
+
color[1],
|
|
478
|
+
color[2],
|
|
479
|
+
color[3] * (runCoverage / sampleOffsets.length)
|
|
480
|
+
];
|
|
481
|
+
pushRectBox(out, runX, py, maxX - runX + 1, 1, alphaColor);
|
|
482
|
+
}
|
|
374
483
|
}
|
|
375
484
|
};
|
|
376
485
|
switch (cp) {
|
|
@@ -411,16 +520,10 @@ function drawBoxDrawing(cp, x, y, cellW, cellH, color, out) {
|
|
|
411
520
|
dashedV(2, heavy2);
|
|
412
521
|
return true;
|
|
413
522
|
case 9581:
|
|
414
|
-
drawArc("br");
|
|
415
|
-
return true;
|
|
416
523
|
case 9582:
|
|
417
|
-
drawArc("bl");
|
|
418
|
-
return true;
|
|
419
524
|
case 9583:
|
|
420
|
-
drawArc("tl");
|
|
421
|
-
return true;
|
|
422
525
|
case 9584:
|
|
423
|
-
|
|
526
|
+
drawRoundedCorner(cp);
|
|
424
527
|
return true;
|
|
425
528
|
case 9585:
|
|
426
529
|
drawDiagonal("ur_ll");
|
|
@@ -437,8 +540,7 @@ function drawBoxDrawing(cp, x, y, cellW, cellH, color, out) {
|
|
|
437
540
|
}
|
|
438
541
|
}
|
|
439
542
|
const [up, right, down, left] = spec;
|
|
440
|
-
const
|
|
441
|
-
const light = Math.max(1, Math.round(minDim * 0.08));
|
|
543
|
+
const light = Math.max(1, Math.round(cellH * 0.08));
|
|
442
544
|
const heavy = Math.max(light + 1, Math.round(light * 1.8));
|
|
443
545
|
const gap = Math.max(1, Math.round(light));
|
|
444
546
|
const cx = x + cellW * 0.5;
|
|
@@ -7642,6 +7744,7 @@ var KITTY_KEYPAD_BY_CODE = {
|
|
|
7642
7744
|
NumpadEnter: { code: 57414, final: "u" },
|
|
7643
7745
|
NumpadEqual: { code: 57415, final: "u" }
|
|
7644
7746
|
};
|
|
7747
|
+
var KITTY_LOCK_KEYS = new Set(["CapsLock", "NumLock", "ScrollLock"]);
|
|
7645
7748
|
var UN_SHIFTED_CODE_BY_CODE = {
|
|
7646
7749
|
Backquote: "`",
|
|
7647
7750
|
Minus: "-",
|
|
@@ -7913,6 +8016,7 @@ function encodeKittyKeyEvent(event, kittyFlags) {
|
|
|
7913
8016
|
const disambiguate = (kittyFlags & KITTY_FLAG_DISAMBIGUATE) !== 0;
|
|
7914
8017
|
const key = event.key ?? "";
|
|
7915
8018
|
const special = KITTY_KEYPAD_BY_CODE[event.code || ""] ?? KITTY_SPECIAL_KEYS[key];
|
|
8019
|
+
const isLockKey = KITTY_LOCK_KEYS.has(key);
|
|
7916
8020
|
const hasText = key.length === 1;
|
|
7917
8021
|
const hasTextModifiers = event.altKey || event.ctrlKey || event.metaKey;
|
|
7918
8022
|
const eventType = kittyEventType(event, reportEvents);
|
|
@@ -7925,6 +8029,8 @@ function encodeKittyKeyEvent(event, kittyFlags) {
|
|
|
7925
8029
|
return "";
|
|
7926
8030
|
if (isRelease && isLegacyControlKey)
|
|
7927
8031
|
return "";
|
|
8032
|
+
if (isLockKey && !reportAll)
|
|
8033
|
+
return "";
|
|
7928
8034
|
if (isLegacyTextKey) {
|
|
7929
8035
|
return key;
|
|
7930
8036
|
}
|
|
@@ -8505,7 +8611,7 @@ class OutputFilter {
|
|
|
8505
8611
|
const altMode = parsePrivateModeSeq(seq);
|
|
8506
8612
|
if (altMode) {
|
|
8507
8613
|
const { enabled, codes } = altMode;
|
|
8508
|
-
if (codes.some((code) => code === 47 || code === 1047 || code ===
|
|
8614
|
+
if (codes.some((code) => code === 47 || code === 1047 || code === 1049)) {
|
|
8509
8615
|
this.altScreen = enabled;
|
|
8510
8616
|
}
|
|
8511
8617
|
}
|
|
@@ -8823,8 +8929,9 @@ function isSymbolCp2(cp) {
|
|
|
8823
8929
|
const isBlockElement2 = cp >= 9600 && cp <= 9631;
|
|
8824
8930
|
const isLegacyComputing2 = cp >= 129792 && cp <= 130047 || cp >= 117760 && cp <= 118463;
|
|
8825
8931
|
const isPowerline2 = cp >= 57520 && cp <= 57559;
|
|
8932
|
+
const isTransportControl = cp >= 9193 && cp <= 9210;
|
|
8826
8933
|
const isGraphicsElement2 = isBoxDrawing2 || isBlockElement2 || isLegacyComputing2 || isPowerline2;
|
|
8827
|
-
return isPrivateUse2 || isGraphicsElement2;
|
|
8934
|
+
return isPrivateUse2 || isGraphicsElement2 || isTransportControl;
|
|
8828
8935
|
}
|
|
8829
8936
|
function pickFontIndexForText(state, text, expectedSpan, shapeClusterWithFont) {
|
|
8830
8937
|
if (!state.fonts.length)
|
|
@@ -50433,6 +50540,10 @@ function createResttyApp(options) {
|
|
|
50433
50540
|
const BACKGROUND_RENDER_FPS = 15;
|
|
50434
50541
|
const GLYPH_SHAPE_CACHE_LIMIT = 12000;
|
|
50435
50542
|
const FONT_PICK_CACHE_LIMIT = 16000;
|
|
50543
|
+
const OVERLAY_SCROLLBAR_WIDTH_CSS_PX = 7;
|
|
50544
|
+
const OVERLAY_SCROLLBAR_MARGIN_CSS_PX = 4;
|
|
50545
|
+
const OVERLAY_SCROLLBAR_INSET_Y_CSS_PX = 2;
|
|
50546
|
+
const OVERLAY_SCROLLBAR_MIN_THUMB_CSS_PX = 28;
|
|
50436
50547
|
let paused = false;
|
|
50437
50548
|
let backend = "none";
|
|
50438
50549
|
let preferredRenderer = options.renderer ?? "auto";
|
|
@@ -50710,30 +50821,32 @@ function createResttyApp(options) {
|
|
|
50710
50821
|
y: (event.clientY - rect.top) * scaleY
|
|
50711
50822
|
};
|
|
50712
50823
|
}
|
|
50713
|
-
function computeOverlayScrollbarLayout(
|
|
50824
|
+
function computeOverlayScrollbarLayout(total, offset, len) {
|
|
50714
50825
|
if (!(total > len && len > 0))
|
|
50715
50826
|
return null;
|
|
50716
|
-
const
|
|
50717
|
-
const width = Math.max(
|
|
50718
|
-
const margin = Math.max(
|
|
50719
|
-
const insetY = Math.max(
|
|
50720
|
-
const trackX = canvas.width - margin - width;
|
|
50827
|
+
const dpr = Math.max(1, currentDpr || 1);
|
|
50828
|
+
const width = Math.max(1, Math.round(OVERLAY_SCROLLBAR_WIDTH_CSS_PX * dpr));
|
|
50829
|
+
const margin = Math.max(1, Math.round(OVERLAY_SCROLLBAR_MARGIN_CSS_PX * dpr));
|
|
50830
|
+
const insetY = Math.max(0, Math.round(OVERLAY_SCROLLBAR_INSET_Y_CSS_PX * dpr));
|
|
50831
|
+
const trackX = Math.max(0, canvas.width - margin - width);
|
|
50721
50832
|
const trackY = insetY;
|
|
50722
|
-
const trackH = Math.max(width,
|
|
50833
|
+
const trackH = Math.max(width, canvas.height - insetY * 2);
|
|
50723
50834
|
const denom = Math.max(1, total - len);
|
|
50724
|
-
const
|
|
50835
|
+
const dynamicThumbH = Math.round(trackH * (len / total));
|
|
50836
|
+
const minThumbH = Math.max(width, Math.round(OVERLAY_SCROLLBAR_MIN_THUMB_CSS_PX * dpr));
|
|
50837
|
+
const thumbH = Math.min(trackH, Math.max(minThumbH, dynamicThumbH));
|
|
50725
50838
|
const thumbY = trackY + Math.round(offset / denom * (trackH - thumbH));
|
|
50726
50839
|
return { total, offset, len, denom, width, trackX, trackY, trackH, thumbY, thumbH };
|
|
50727
50840
|
}
|
|
50728
50841
|
function getOverlayScrollbarLayout() {
|
|
50729
50842
|
if (!showOverlayScrollbar || !wasmExports?.restty_scrollbar_total || !wasmHandle)
|
|
50730
50843
|
return null;
|
|
50731
|
-
if (!gridState.rows
|
|
50844
|
+
if (!gridState.rows)
|
|
50732
50845
|
return null;
|
|
50733
50846
|
const total = wasmExports.restty_scrollbar_total(wasmHandle) || 0;
|
|
50734
50847
|
const offset = wasmExports.restty_scrollbar_offset ? wasmExports.restty_scrollbar_offset(wasmHandle) : 0;
|
|
50735
50848
|
const len = wasmExports.restty_scrollbar_len ? wasmExports.restty_scrollbar_len(wasmHandle) : gridState.rows;
|
|
50736
|
-
return computeOverlayScrollbarLayout(
|
|
50849
|
+
return computeOverlayScrollbarLayout(total, offset, len);
|
|
50737
50850
|
}
|
|
50738
50851
|
function isPointInScrollbarHitArea(layout, x3, y) {
|
|
50739
50852
|
const hitPadX = Math.max(3, Math.round(layout.width * 0.35));
|
|
@@ -50773,10 +50886,10 @@ function createResttyApp(options) {
|
|
|
50773
50886
|
pushRectBox(out, x02 + inset, y02 + height - 1 - row, rowW, 1, color);
|
|
50774
50887
|
}
|
|
50775
50888
|
}
|
|
50776
|
-
function appendOverlayScrollbar(overlayData,
|
|
50889
|
+
function appendOverlayScrollbar(overlayData, total, offset, len) {
|
|
50777
50890
|
if (!showOverlayScrollbar)
|
|
50778
50891
|
return;
|
|
50779
|
-
const layout = computeOverlayScrollbarLayout(
|
|
50892
|
+
const layout = computeOverlayScrollbarLayout(total, offset, len);
|
|
50780
50893
|
if (!layout)
|
|
50781
50894
|
return;
|
|
50782
50895
|
const since = performance.now() - scrollbarState.lastInputAt;
|
|
@@ -51568,6 +51681,9 @@ function createResttyApp(options) {
|
|
|
51568
51681
|
function sendKeyInput(text, source = "key") {
|
|
51569
51682
|
if (!text)
|
|
51570
51683
|
return;
|
|
51684
|
+
if (source !== "program" && (selectionState.active || selectionState.dragging)) {
|
|
51685
|
+
clearSelection();
|
|
51686
|
+
}
|
|
51571
51687
|
if (ptyTransport.isConnected()) {
|
|
51572
51688
|
const payload = inputHandler.mapKeyForPty(text);
|
|
51573
51689
|
ptyTransport.sendInput(payload);
|
|
@@ -51604,6 +51720,14 @@ function createResttyApp(options) {
|
|
|
51604
51720
|
function bindCanvasEvents() {
|
|
51605
51721
|
if (!attachCanvasEvents)
|
|
51606
51722
|
return;
|
|
51723
|
+
const shouldRoutePointerToAppMouse = (shiftKey) => {
|
|
51724
|
+
if (shiftKey)
|
|
51725
|
+
return false;
|
|
51726
|
+
if (!inputHandler.isMouseActive())
|
|
51727
|
+
return false;
|
|
51728
|
+
return inputHandler.isAltScreen ? inputHandler.isAltScreen() : false;
|
|
51729
|
+
};
|
|
51730
|
+
const shouldPreferLocalPrimarySelection = (event) => !isTouchPointer(event) && event.button === 0 && !event.altKey;
|
|
51607
51731
|
canvas.style.touchAction = touchSelectionMode === "long-press" || touchSelectionMode === "drag" ? "none" : "pan-y pinch-zoom";
|
|
51608
51732
|
const onPointerDown = (event) => {
|
|
51609
51733
|
if (!isTouchPointer(event) && event.button === 0) {
|
|
@@ -51623,7 +51747,7 @@ function createResttyApp(options) {
|
|
|
51623
51747
|
}
|
|
51624
51748
|
}
|
|
51625
51749
|
}
|
|
51626
|
-
if (inputHandler.sendMouseEvent("down", event)) {
|
|
51750
|
+
if (shouldRoutePointerToAppMouse(event.shiftKey) && !shouldPreferLocalPrimarySelection(event) && inputHandler.sendMouseEvent("down", event)) {
|
|
51627
51751
|
event.preventDefault();
|
|
51628
51752
|
canvas.setPointerCapture?.(event.pointerId);
|
|
51629
51753
|
return;
|
|
@@ -51674,10 +51798,6 @@ function createResttyApp(options) {
|
|
|
51674
51798
|
event.preventDefault();
|
|
51675
51799
|
return;
|
|
51676
51800
|
}
|
|
51677
|
-
if (inputHandler.sendMouseEvent("move", event)) {
|
|
51678
|
-
event.preventDefault();
|
|
51679
|
-
return;
|
|
51680
|
-
}
|
|
51681
51801
|
if (isTouchPointer(event)) {
|
|
51682
51802
|
if (touchSelectionState.pendingPointerId === event.pointerId) {
|
|
51683
51803
|
const dx = event.clientX - touchSelectionState.pendingStartX;
|
|
@@ -51715,15 +51835,19 @@ function createResttyApp(options) {
|
|
|
51715
51835
|
return;
|
|
51716
51836
|
}
|
|
51717
51837
|
const cell = normalizeSelectionCell(positionToCell(event));
|
|
51718
|
-
if (
|
|
51719
|
-
|
|
51838
|
+
if (selectionState.dragging) {
|
|
51839
|
+
event.preventDefault();
|
|
51840
|
+
selectionState.focus = cell;
|
|
51841
|
+
updateLinkHover(null);
|
|
51842
|
+
updateCanvasCursor();
|
|
51843
|
+
needsRender = true;
|
|
51720
51844
|
return;
|
|
51721
51845
|
}
|
|
51722
|
-
event.
|
|
51723
|
-
|
|
51724
|
-
|
|
51725
|
-
|
|
51726
|
-
|
|
51846
|
+
if (shouldRoutePointerToAppMouse(event.shiftKey) && inputHandler.sendMouseEvent("move", event)) {
|
|
51847
|
+
event.preventDefault();
|
|
51848
|
+
return;
|
|
51849
|
+
}
|
|
51850
|
+
updateLinkHover(cell);
|
|
51727
51851
|
};
|
|
51728
51852
|
const onPointerUp = (event) => {
|
|
51729
51853
|
if (scrollbarDragState.pointerId === event.pointerId) {
|
|
@@ -51731,10 +51855,6 @@ function createResttyApp(options) {
|
|
|
51731
51855
|
event.preventDefault();
|
|
51732
51856
|
return;
|
|
51733
51857
|
}
|
|
51734
|
-
if (inputHandler.sendMouseEvent("up", event)) {
|
|
51735
|
-
event.preventDefault();
|
|
51736
|
-
return;
|
|
51737
|
-
}
|
|
51738
51858
|
if (isTouchPointer(event)) {
|
|
51739
51859
|
if (touchSelectionState.pendingPointerId === event.pointerId) {
|
|
51740
51860
|
clearPendingTouchSelection();
|
|
@@ -51773,6 +51893,10 @@ function createResttyApp(options) {
|
|
|
51773
51893
|
needsRender = true;
|
|
51774
51894
|
}
|
|
51775
51895
|
} else {
|
|
51896
|
+
if (shouldRoutePointerToAppMouse(event.shiftKey) && !shouldPreferLocalPrimarySelection(event) && inputHandler.sendMouseEvent("up", event)) {
|
|
51897
|
+
event.preventDefault();
|
|
51898
|
+
return;
|
|
51899
|
+
}
|
|
51776
51900
|
updateLinkHover(cell);
|
|
51777
51901
|
}
|
|
51778
51902
|
if (!selectionState.active && event.button === 0 && linkState.hoverUri) {
|
|
@@ -51801,9 +51925,7 @@ function createResttyApp(options) {
|
|
|
51801
51925
|
}
|
|
51802
51926
|
};
|
|
51803
51927
|
const onWheel = (event) => {
|
|
51804
|
-
|
|
51805
|
-
const altScreen = inputHandler.isAltScreen ? inputHandler.isAltScreen() : false;
|
|
51806
|
-
if (mouseActive && altScreen && !event.shiftKey) {
|
|
51928
|
+
if (shouldRoutePointerToAppMouse(event.shiftKey)) {
|
|
51807
51929
|
if (inputHandler.sendMouseEvent("wheel", event)) {
|
|
51808
51930
|
event.preventDefault();
|
|
51809
51931
|
return;
|
|
@@ -53224,14 +53346,14 @@ function createResttyApp(options) {
|
|
|
53224
53346
|
isFocused = true;
|
|
53225
53347
|
focusTypingInput();
|
|
53226
53348
|
if (inputHandler?.isFocusReporting?.()) {
|
|
53227
|
-
sendKeyInput("\x1B[I");
|
|
53349
|
+
sendKeyInput("\x1B[I", "program");
|
|
53228
53350
|
}
|
|
53229
53351
|
};
|
|
53230
53352
|
const handleBlur = () => {
|
|
53231
53353
|
const stillFocused = typeof document !== "undefined" && imeInput ? document.activeElement === imeInput : false;
|
|
53232
53354
|
isFocused = stillFocused;
|
|
53233
53355
|
if (!stillFocused && inputHandler?.isFocusReporting?.()) {
|
|
53234
|
-
sendKeyInput("\x1B[O");
|
|
53356
|
+
sendKeyInput("\x1B[O", "program");
|
|
53235
53357
|
}
|
|
53236
53358
|
};
|
|
53237
53359
|
const handlePointerFocus = () => {
|
|
@@ -54679,11 +54801,20 @@ function createResttyApp(options) {
|
|
|
54679
54801
|
let gw = metrics.width * bitmapScale;
|
|
54680
54802
|
let gh = metrics.height * bitmapScale;
|
|
54681
54803
|
if (symbolLike && !glyphConstrained) {
|
|
54682
|
-
const
|
|
54683
|
-
if (
|
|
54684
|
-
bitmapScale *=
|
|
54685
|
-
gw *=
|
|
54686
|
-
gh *=
|
|
54804
|
+
const scaleToFit = gw > 0 && gh > 0 ? Math.min(maxWidth / gw, maxHeight / gh) : 1;
|
|
54805
|
+
if (scaleToFit < 1) {
|
|
54806
|
+
bitmapScale *= scaleToFit;
|
|
54807
|
+
gw *= scaleToFit;
|
|
54808
|
+
gh *= scaleToFit;
|
|
54809
|
+
} else if (symbolFont && item.shaped.glyphs.length === 1 && gh > 0) {
|
|
54810
|
+
const targetHeight = Math.min(maxHeight, nerdMetrics.iconHeightSingle);
|
|
54811
|
+
const growToHeight = targetHeight > 0 ? targetHeight / gh : 1;
|
|
54812
|
+
const growScale = Math.min(scaleToFit, growToHeight);
|
|
54813
|
+
if (growScale > 1) {
|
|
54814
|
+
bitmapScale *= growScale;
|
|
54815
|
+
gw *= growScale;
|
|
54816
|
+
gh *= growScale;
|
|
54817
|
+
}
|
|
54687
54818
|
}
|
|
54688
54819
|
gw = Math.round(gw);
|
|
54689
54820
|
gh = Math.round(gh);
|
|
@@ -54723,7 +54854,9 @@ function createResttyApp(options) {
|
|
|
54723
54854
|
}
|
|
54724
54855
|
}
|
|
54725
54856
|
if (!glyphConstrained && !constrained && symbolFont && item.shaped.glyphs.length === 1) {
|
|
54857
|
+
const rowY = item.baseY - yPad - baselineOffset;
|
|
54726
54858
|
x3 = item.x + (maxWidth - gw) * 0.5;
|
|
54859
|
+
y = rowY + (cellH - gh) * 0.5;
|
|
54727
54860
|
}
|
|
54728
54861
|
if (!constrained && symbolLike && !symbolFont) {
|
|
54729
54862
|
const rowY = item.baseY - yPad - baselineOffset;
|
|
@@ -54819,7 +54952,7 @@ function createResttyApp(options) {
|
|
|
54819
54952
|
scrollbarState.lastOffset = offset;
|
|
54820
54953
|
scrollbarState.lastLen = len;
|
|
54821
54954
|
}
|
|
54822
|
-
appendOverlayScrollbar(overlayData,
|
|
54955
|
+
appendOverlayScrollbar(overlayData, total, offset, len);
|
|
54823
54956
|
}
|
|
54824
54957
|
webgpuUniforms[0] = canvas.width;
|
|
54825
54958
|
webgpuUniforms[1] = canvas.height;
|
|
@@ -55509,7 +55642,7 @@ function createResttyApp(options) {
|
|
|
55509
55642
|
scrollbarState.lastOffset = offset;
|
|
55510
55643
|
scrollbarState.lastLen = len;
|
|
55511
55644
|
}
|
|
55512
|
-
appendOverlayScrollbar(overlayData,
|
|
55645
|
+
appendOverlayScrollbar(overlayData, total, offset, len);
|
|
55513
55646
|
}
|
|
55514
55647
|
for (const [fontIndex, neededIds] of neededGlyphIdsByFont.entries()) {
|
|
55515
55648
|
const fontEntry = fontState.fonts[fontIndex];
|
|
@@ -55646,11 +55779,20 @@ function createResttyApp(options) {
|
|
|
55646
55779
|
let gw = metrics.width * bitmapScale;
|
|
55647
55780
|
let gh = metrics.height * bitmapScale;
|
|
55648
55781
|
if (symbolLike && !glyphConstrained) {
|
|
55649
|
-
const
|
|
55650
|
-
if (
|
|
55651
|
-
bitmapScale *=
|
|
55652
|
-
gw *=
|
|
55653
|
-
gh *=
|
|
55782
|
+
const scaleToFit = gw > 0 && gh > 0 ? Math.min(maxWidth / gw, maxHeight / gh) : 1;
|
|
55783
|
+
if (scaleToFit < 1) {
|
|
55784
|
+
bitmapScale *= scaleToFit;
|
|
55785
|
+
gw *= scaleToFit;
|
|
55786
|
+
gh *= scaleToFit;
|
|
55787
|
+
} else if (symbolFont && item.shaped.glyphs.length === 1 && gh > 0) {
|
|
55788
|
+
const targetHeight = Math.min(maxHeight, nerdMetrics.iconHeightSingle);
|
|
55789
|
+
const growToHeight = targetHeight > 0 ? targetHeight / gh : 1;
|
|
55790
|
+
const growScale = Math.min(scaleToFit, growToHeight);
|
|
55791
|
+
if (growScale > 1) {
|
|
55792
|
+
bitmapScale *= growScale;
|
|
55793
|
+
gw *= growScale;
|
|
55794
|
+
gh *= growScale;
|
|
55795
|
+
}
|
|
55654
55796
|
}
|
|
55655
55797
|
gw = Math.round(gw);
|
|
55656
55798
|
gh = Math.round(gh);
|
|
@@ -55688,7 +55830,9 @@ function createResttyApp(options) {
|
|
|
55688
55830
|
}
|
|
55689
55831
|
}
|
|
55690
55832
|
if (!glyphConstrained && !constrained && symbolFont && item.shaped.glyphs.length === 1) {
|
|
55833
|
+
const rowY = item.baseY - yPad - baselineOffset;
|
|
55691
55834
|
x3 = item.x + (maxWidth - gw) * 0.5;
|
|
55835
|
+
y = rowY + (cellH - gh) * 0.5;
|
|
55692
55836
|
}
|
|
55693
55837
|
if (!constrained && symbolLike && !symbolFont) {
|
|
55694
55838
|
const rowY = item.baseY - yPad - baselineOffset;
|
|
@@ -55885,7 +56029,7 @@ function createResttyApp(options) {
|
|
|
55885
56029
|
}
|
|
55886
56030
|
appendLog(`[key] ${JSON.stringify(normalized)}${before}`);
|
|
55887
56031
|
}
|
|
55888
|
-
if (source
|
|
56032
|
+
if (source === "key" && (selectionState.active || selectionState.dragging)) {
|
|
55889
56033
|
clearSelection();
|
|
55890
56034
|
}
|
|
55891
56035
|
if (source === "pty" && linkState.hoverId)
|