From 51f64e7ca8f9e9913840611cbcfffafa6eeb7211 Mon Sep 17 00:00:00 2001 From: Gregor Lohaus Date: Sun, 31 May 2026 19:56:09 +0200 Subject: [PATCH] cache hidden panes --- .../com/gregor/jprototerm/Compositor.java | 36 ++++++++++++++----- src/main/java/com/gregor/jprototerm/Tab.java | 7 ++++ 2 files changed, 35 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/gregor/jprototerm/Compositor.java b/src/main/java/com/gregor/jprototerm/Compositor.java index 6874a73..f29c22e 100644 --- a/src/main/java/com/gregor/jprototerm/Compositor.java +++ b/src/main/java/com/gregor/jprototerm/Compositor.java @@ -162,6 +162,14 @@ public final class Compositor { return tabs.isEmpty() ? List.of() : currentTab().panes(); } + private List allOpenPanes() { + List panes = new ArrayList<>(); + for (Tab tab : tabs) { + panes.addAll(tab.allPanes()); + } + return panes; + } + private boolean isActive(TerminalPane pane) { return !tabs.isEmpty() && currentTab().isActive(pane); } @@ -180,8 +188,9 @@ public final class Compositor { long contentVersion = tabs.isEmpty() ? 0 : currentTab().contentVersion(); boolean geometryChanged = width != lastWidth || height != lastHeight; boolean contentChanged = contentVersion != lastContentVersion; + boolean syncScene = sceneDirty || geometryChanged; - if (!sceneDirty && !geometryChanged && !contentChanged) { + if (!syncScene && !contentChanged) { return; } @@ -189,14 +198,17 @@ public final class Compositor { lastHeight = height; lastContentVersion = contentVersion; sceneDirty = false; - renderFrame(width, height); + if (syncScene) { + syncSceneGraph(width, height); + } + renderVisiblePanes(); } private void markSceneDirty() { sceneDirty = true; } - private void renderFrame(double width, double height) { + private void syncSceneGraph(double width, double height) { double topInset = tabs.size() > 1 ? TAB_BAR_HEIGHT : 0.0; paneLayer.resizeRelocate(0.0, 0.0, width, height); @@ -207,18 +219,26 @@ public final class Compositor { } List panes = currentPanes(); - retainNodes(panes); + retainNodes(allOpenPanes()); List orderedNodes = new ArrayList<>(panes.size()); for (TerminalPane pane : panes) { pane.fitToBounds(); TerminalPaneNode node = nodeFor(pane); node.resizeRelocate(Math.round(pane.x()), Math.round(pane.y()), pane.width(), pane.height()); - node.renderIncremental(isActive(pane)); orderedNodes.add(node); } paneLayer.getChildren().setAll(orderedNodes); } + private void renderVisiblePanes() { + for (TerminalPane pane : currentPanes()) { + TerminalPaneNode node = nodes.get(pane); + if (node != null) { + node.renderIncremental(isActive(pane)); + } + } + } + private TerminalPaneNode nodeFor(TerminalPane pane) { return nodes.computeIfAbsent(pane, this::createNode); } @@ -233,9 +253,9 @@ public final class Compositor { return node; } - private void retainNodes(List visiblePanes) { - Set visible = new HashSet<>(visiblePanes); - nodes.keySet().removeIf(pane -> !visible.contains(pane)); + private void retainNodes(List openPanes) { + Set open = new HashSet<>(openPanes); + nodes.keySet().removeIf(pane -> !open.contains(pane)); } private void updateTabBar(double width, double barHeight) { diff --git a/src/main/java/com/gregor/jprototerm/Tab.java b/src/main/java/com/gregor/jprototerm/Tab.java index ddc53e1..b112484 100644 --- a/src/main/java/com/gregor/jprototerm/Tab.java +++ b/src/main/java/com/gregor/jprototerm/Tab.java @@ -75,6 +75,13 @@ final class Tab implements AutoCloseable { return List.copyOf(ordered); } + List allPanes() { + List all = new ArrayList<>(tiled.size() + floating.size()); + all.addAll(tiled); + all.addAll(floating); + return List.copyOf(all); + } + boolean isActive(TerminalPane pane) { return pane != null && pane == active; }