From c3d16c91e94ca4d998c5bb49c1b294a903b1954d Mon Sep 17 00:00:00 2001 From: "Klare, Heiko" Date: Wed, 25 Feb 2026 10:36:03 +0100 Subject: [PATCH 1/2] Make double buffering of Terminal adopt to higher monitor zooms The terminal implementation uses a custom double buffering implementation for rendering the current line. On most Platforms (Linux and MacOS) the current implementation will always render the double-buffered image at 100% zoom, even if the target zoom is higher. This change adapts the implementation to directly render into the actual control and enable native double buffering for the control instead. This ensures that the contents are rendered at the actual target zoom, producing sharper results on HiDPI monitors when using MacOS or Linux. Fixes https://github.com/eclipse-platform/eclipse.platform/issues/2295 Fixes https://github.com/eclipse-platform/eclipse.platform/issues/2191 # Conflicts: # terminal/bundles/org.eclipse.terminal.control/src/org/eclipse/terminal/internal/textcanvas/TextLineRenderer.java --- .../internal/textcanvas/TextCanvas.java | 2 +- .../internal/textcanvas/TextLineRenderer.java | 28 ++++++++----------- 2 files changed, 12 insertions(+), 18 deletions(-) diff --git a/terminal/bundles/org.eclipse.terminal.control/src/org/eclipse/terminal/internal/textcanvas/TextCanvas.java b/terminal/bundles/org.eclipse.terminal.control/src/org/eclipse/terminal/internal/textcanvas/TextCanvas.java index 26ab7916d09..298c949866c 100644 --- a/terminal/bundles/org.eclipse.terminal.control/src/org/eclipse/terminal/internal/textcanvas/TextCanvas.java +++ b/terminal/bundles/org.eclipse.terminal.control/src/org/eclipse/terminal/internal/textcanvas/TextCanvas.java @@ -101,7 +101,7 @@ private enum SelectionMode { * (SWT.H_SCROLL and SWT.V_SCROLL are automatically added). */ public TextCanvas(Composite parent, ITextCanvasModel model, int style, ILinelRenderer cellRenderer) { - super(parent, style | SWT.H_SCROLL | SWT.V_SCROLL); + super(parent, style | SWT.H_SCROLL | SWT.V_SCROLL | SWT.DOUBLE_BUFFERED); fCellRenderer = cellRenderer; setCellWidth(fCellRenderer.getCellWidth()); setCellHeight(fCellRenderer.getCellHeight()); diff --git a/terminal/bundles/org.eclipse.terminal.control/src/org/eclipse/terminal/internal/textcanvas/TextLineRenderer.java b/terminal/bundles/org.eclipse.terminal.control/src/org/eclipse/terminal/internal/textcanvas/TextLineRenderer.java index a5075c2f672..9219bc91e7c 100644 --- a/terminal/bundles/org.eclipse.terminal.control/src/org/eclipse/terminal/internal/textcanvas/TextLineRenderer.java +++ b/terminal/bundles/org.eclipse.terminal.control/src/org/eclipse/terminal/internal/textcanvas/TextLineRenderer.java @@ -21,7 +21,6 @@ import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Font; import org.eclipse.swt.graphics.GC; -import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.graphics.RGB; import org.eclipse.terminal.connector.Logger; @@ -61,21 +60,19 @@ public void drawLine(ITextCanvasModel model, GC gc, int line, int x, int y, int if (width <= 0 || height <= 0) { return; } - Image buffer = new Image(gc.getDevice(), width, height); - GC doubleBufferGC = new GC(buffer); if (line < 0 || line >= getTerminalText().getHeight() || colFirst >= getTerminalText().getWidth() || colFirst - colLast == 0) { - fillBackground(doubleBufferGC, 0, 0, width, height); + fillBackground(gc, x, y, width, height); } else { colLast = Math.min(colLast, getTerminalText().getWidth()); LineSegment[] segments = getTerminalText().getLineSegments(line, colFirst, colLast - colFirst); for (int i = 0; i < segments.length; i++) { LineSegment segment = segments[i]; TerminalStyle style = segment.getStyle(); - setupGC(doubleBufferGC, style); + setupGC(gc, style); String text = segment.getText(); - drawText(doubleBufferGC, 0, 0, colFirst, segment.getColumn(), text); - drawCursor(model, doubleBufferGC, line, 0, 0, colFirst); + drawText(gc, x, y, colFirst, segment.getColumn(), text); + drawCursor(model, gc, line, x, y, colFirst); } if (fModel.hasHoverSelection(line)) { if (DEBUG_HOVER) { @@ -87,14 +84,14 @@ public void drawLine(ITextCanvasModel model, GC gc, int line, int x, int y, int int colEnd = line == hsEnd.y ? hsEnd.x : getTerminalText().getWidth(); if (colStart < colEnd) { RGB defaultFg = fStyleMap.getForegrondRGB(null); - doubleBufferGC.setForeground(new Color(doubleBufferGC.getDevice(), defaultFg)); - drawUnderline(doubleBufferGC, colStart, colEnd); + gc.setForeground(new Color(gc.getDevice(), defaultFg)); + drawUnderline(gc, x, y, colStart, colEnd); } } if (fModel.hasLineSelection(line)) { TerminalStyle style = TerminalStyle.getStyle(TerminalColor.SELECTION_FOREGROUND, TerminalColor.SELECTION_BACKGROUND); - setupGC(doubleBufferGC, style); + setupGC(gc, style); Point start = model.getSelectionStart(); Point end = model.getSelectionEnd(); char[] chars = model.getTerminalText().getChars(line); @@ -113,14 +110,11 @@ public void drawLine(ITextCanvasModel model, GC gc, int line, int x, int y, int len = Math.min(len, chars.length - offset); if (len > 0) { String text = new String(chars, offset, len); - drawText(doubleBufferGC, 0, 0, colFirst, offset, text); + drawText(gc, x, y, colFirst, offset, text); } } } } - gc.drawImage(buffer, x, y); - doubleBufferGC.dispose(); - buffer.dispose(); } private void fillBackground(GC gc, int x, int y, int width, int height) { @@ -186,9 +180,9 @@ private void drawText(GC gc, int x, int y, int colFirst, int col, String text) { * @param colStart Starting text column to underline (inclusive) * @param colEnd Ending text column to underline (inclusive) */ - private void drawUnderline(GC gc, int colStart, int colEnd) { - int y = getCellHeight() - 1; - int x = getCellWidth() * colStart; + private void drawUnderline(GC gc, int xOffset, int yOffset, int colStart, int colEnd) { + int y = yOffset + getCellHeight() - 1; + int x = xOffset + getCellWidth() * colStart; // x2 is the right side of last column being underlined. int x2 = (colEnd + 1) * getCellWidth() - 1; From 9ec63b9963101e174b8a02eae243084ab5ba88e9 Mon Sep 17 00:00:00 2001 From: "Klare, Heiko" Date: Thu, 26 Feb 2026 11:41:24 +0100 Subject: [PATCH 2/2] Avoid cut-off symbols in Terminal On monitors with zoom != 100% on Windows, symbols in the Terminal appear cut-off. This can be avoided by enabled advanced mode for the GC used for rendering the text. --- .../src/org/eclipse/terminal/internal/textcanvas/GridCanvas.java | 1 + 1 file changed, 1 insertion(+) diff --git a/terminal/bundles/org.eclipse.terminal.control/src/org/eclipse/terminal/internal/textcanvas/GridCanvas.java b/terminal/bundles/org.eclipse.terminal.control/src/org/eclipse/terminal/internal/textcanvas/GridCanvas.java index c3384f57260..b4601c6068f 100644 --- a/terminal/bundles/org.eclipse.terminal.control/src/org/eclipse/terminal/internal/textcanvas/GridCanvas.java +++ b/terminal/bundles/org.eclipse.terminal.control/src/org/eclipse/terminal/internal/textcanvas/GridCanvas.java @@ -45,6 +45,7 @@ public GridCanvas(Composite parent, int style) { */ @Override protected void paint(GC gc) { + gc.setAdvanced(true); Rectangle clipping = gc.getClipping(); if (clipping.width == 0 || clipping.height == 0) { return;