port feasable performance improvements
This commit is contained in:
@@ -365,7 +365,10 @@ public final class Compositor {
|
||||
double ey = localY(event.getY(), target);
|
||||
KeyModifiers modifiers = modifiers(event);
|
||||
for (int i = 0; i < rows; i++) {
|
||||
sent |= send(pane, target, MouseInput.press(wheelButton, ex, ey, modifiers), mouseButtonPressed, event);
|
||||
if (!send(pane, target, MouseInput.press(wheelButton, ex, ey, modifiers), mouseButtonPressed, event)) {
|
||||
break;
|
||||
}
|
||||
sent = true;
|
||||
}
|
||||
}
|
||||
if (!sent) {
|
||||
|
||||
@@ -14,6 +14,7 @@ import dev.jlibghostty.Terminal;
|
||||
import dev.jlibghostty.TerminalOptions;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
/**
|
||||
* One terminal: owns its ghostty {@link Terminal}, the {@link ShellSession}/pty driving it,
|
||||
@@ -41,8 +42,8 @@ public final class TerminalPane implements AutoCloseable {
|
||||
private int rows;
|
||||
private int pixelWidth;
|
||||
private int pixelHeight;
|
||||
private long contentVersion;
|
||||
private long snapshotVersion = -1;
|
||||
private final AtomicLong contentVersion = new AtomicLong();
|
||||
private volatile long snapshotVersion = -1;
|
||||
|
||||
private TerminalPane(Terminal terminal, TerminalMetrics metrics, boolean kittyEnabled,
|
||||
Runnable onContentChange, int columns, int rows) {
|
||||
@@ -157,16 +158,17 @@ public final class TerminalPane implements AutoCloseable {
|
||||
|
||||
private RenderStateSnapshot takeSnapshot(boolean full) {
|
||||
synchronized (terminal) {
|
||||
long version = contentVersion.get();
|
||||
if (full) {
|
||||
renderState.update(terminal);
|
||||
cachedSnapshot = renderState.snapshot();
|
||||
renderState.resetDirty();
|
||||
snapshotVersion = contentVersion;
|
||||
} else if (snapshotVersion != contentVersion) {
|
||||
snapshotVersion = version;
|
||||
} else if (snapshotVersion != version) {
|
||||
renderState.update(terminal);
|
||||
cachedSnapshot = renderState.snapshotIncremental();
|
||||
renderState.resetDirty();
|
||||
snapshotVersion = contentVersion;
|
||||
snapshotVersion = version;
|
||||
}
|
||||
return cachedSnapshot;
|
||||
}
|
||||
@@ -180,15 +182,11 @@ public final class TerminalPane implements AutoCloseable {
|
||||
|
||||
/** This pane's own content revision, bumped on every change (see {@link #refresh()}). */
|
||||
public long contentVersion() {
|
||||
synchronized (terminal) {
|
||||
return contentVersion;
|
||||
}
|
||||
return contentVersion.get();
|
||||
}
|
||||
|
||||
long snapshotVersion() {
|
||||
synchronized (terminal) {
|
||||
return snapshotVersion;
|
||||
}
|
||||
return snapshotVersion;
|
||||
}
|
||||
|
||||
public boolean kittyEnabled() {
|
||||
@@ -256,7 +254,7 @@ public final class TerminalPane implements AutoCloseable {
|
||||
// Mark this pane's content dirty (the snapshot is computed lazily in the paint path,
|
||||
// so a burst of writes collapses into one snapshot per frame) and tell the owning tab
|
||||
// one of its panes changed.
|
||||
contentVersion++;
|
||||
contentVersion.incrementAndGet();
|
||||
onContentChange.run();
|
||||
}
|
||||
|
||||
|
||||
@@ -603,6 +603,27 @@ final class TerminalPaneNode extends Region {
|
||||
return cellBackgroundColor(firstCell ? cells.get(0) : cells.get(cells.size() - 1));
|
||||
}
|
||||
|
||||
private static Color cellBackgroundOverride(RenderCell cell) {
|
||||
if (cell.inverse()) {
|
||||
var fg = cell.foreground();
|
||||
return fg.isPresent() ? toFxColor(fg.get()) : DEFAULT_FOREGROUND;
|
||||
}
|
||||
var bg = cell.background();
|
||||
return bg.isPresent() ? toFxColor(bg.get()) : null;
|
||||
}
|
||||
|
||||
private static Color cellForegroundColor(RenderCell cell) {
|
||||
var fgOpt = cell.foreground();
|
||||
var bgOpt = cell.background();
|
||||
Color fg = fgOpt.isPresent() ? toFxColor(fgOpt.get()) : DEFAULT_FOREGROUND;
|
||||
Color bg = bgOpt.isPresent() ? toFxColor(bgOpt.get()) : null;
|
||||
|
||||
if (cell.inverse()) {
|
||||
return (bg != null) ? bg : PANE_BACKGROUND;
|
||||
}
|
||||
return fg;
|
||||
}
|
||||
|
||||
private static Color toFxColor(RenderColor color) {
|
||||
int key = (color.red() << 16) | (color.green() << 8) | color.blue();
|
||||
Color cached = COLOR_CACHE.get(key);
|
||||
@@ -709,37 +730,61 @@ final class TerminalPaneNode extends Region {
|
||||
double contentTop = TerminalMetrics.PADDING + row.row() * lineHeight;
|
||||
double localCellTop = contentTop - rowTop;
|
||||
double baseline = TerminalMetrics.PADDING + metrics.baselineOffset() + row.row() * lineHeight - rowTop;
|
||||
drawRowBackgrounds(gc, row, localCellTop, cellWidth, lineHeight);
|
||||
drawRowText(gc, row, baseline, cellWidth);
|
||||
}
|
||||
|
||||
private void drawRowBackgrounds(GraphicsContext gc, RenderRow row, double localCellTop, double cellWidth, double lineHeight) {
|
||||
Color runBackground = null;
|
||||
int runStartColumn = 0;
|
||||
int previousColumn = -1;
|
||||
for (RenderCell cell : row.cells()) {
|
||||
if (cell.kittyPlaceholder().isPresent()) {
|
||||
flushBackgroundRun(gc, runBackground, localCellTop, cellWidth, lineHeight, runStartColumn, previousColumn);
|
||||
runBackground = null;
|
||||
previousColumn = -1;
|
||||
continue;
|
||||
}
|
||||
|
||||
double x = TerminalMetrics.PADDING + cell.column() * cellWidth;
|
||||
var fgOpt = cell.foreground();
|
||||
var bgOpt = cell.background();
|
||||
Color fg = fgOpt.isPresent() ? toFxColor(fgOpt.get()) : DEFAULT_FOREGROUND;
|
||||
Color bg = bgOpt.isPresent() ? toFxColor(bgOpt.get()) : null;
|
||||
|
||||
if (cell.inverse()) {
|
||||
Color swappedBg = fg;
|
||||
fg = (bg != null) ? bg : PANE_BACKGROUND;
|
||||
bg = swappedBg;
|
||||
}
|
||||
|
||||
if (bg != null) {
|
||||
gc.setFill(bg);
|
||||
gc.fillRect(x, localCellTop, cellWidth, lineHeight);
|
||||
}
|
||||
if (cell.selected()) {
|
||||
gc.setFill(SELECTED_BACKGROUND);
|
||||
gc.fillRect(x, localCellTop, cellWidth, lineHeight);
|
||||
}
|
||||
if (cell.codepoints().length == 0) {
|
||||
Color background = cell.selected() ? SELECTED_BACKGROUND : cellBackgroundOverride(cell);
|
||||
if (background == null) {
|
||||
flushBackgroundRun(gc, runBackground, localCellTop, cellWidth, lineHeight, runStartColumn, previousColumn);
|
||||
runBackground = null;
|
||||
previousColumn = -1;
|
||||
continue;
|
||||
}
|
||||
|
||||
gc.setFill(fg);
|
||||
gc.fillText(cell.text(), x, baseline);
|
||||
if (runBackground == null || background != runBackground || cell.column() != previousColumn + 1) {
|
||||
flushBackgroundRun(gc, runBackground, localCellTop, cellWidth, lineHeight, runStartColumn, previousColumn);
|
||||
runBackground = background;
|
||||
runStartColumn = cell.column();
|
||||
}
|
||||
previousColumn = cell.column();
|
||||
}
|
||||
flushBackgroundRun(gc, runBackground, localCellTop, cellWidth, lineHeight, runStartColumn, previousColumn);
|
||||
}
|
||||
|
||||
private void flushBackgroundRun(GraphicsContext gc, Color background, double localCellTop,
|
||||
double cellWidth, double lineHeight, int startColumn, int endColumn) {
|
||||
if (background == null || endColumn < startColumn) {
|
||||
return;
|
||||
}
|
||||
gc.setFill(background);
|
||||
gc.fillRect(
|
||||
TerminalMetrics.PADDING + startColumn * cellWidth,
|
||||
localCellTop,
|
||||
(endColumn - startColumn + 1) * cellWidth,
|
||||
lineHeight);
|
||||
}
|
||||
|
||||
private void drawRowText(GraphicsContext gc, RenderRow row, double baseline, double cellWidth) {
|
||||
for (RenderCell cell : row.cells()) {
|
||||
if (cell.kittyPlaceholder().isPresent() || cell.codepoints().length == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
gc.setFill(cellForegroundColor(cell));
|
||||
gc.fillText(cell.text(), TerminalMetrics.PADDING + cell.column() * cellWidth, baseline);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user