From 2e83544872034e3836508b67cb58f612a1c3fd11 Mon Sep 17 00:00:00 2001 From: Christopher Hermann Date: Wed, 6 May 2026 09:38:36 +0200 Subject: [PATCH] Fix sticky scroll height calculation for variable line heights When emoji or other content affects line heights, sticky scroll was calculating the total height wrong by assuming all lines were the same. Now it gets the actual height for each line instead. Also fixes the height check for limiting visible lines. --- .../stickyscroll/StickyScrollingControl.java | 8 ++++-- .../StickyScrollingControlTest.java | 28 +++++++++++++++++++ 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/bundles/org.eclipse.ui.editors/src/org/eclipse/ui/internal/texteditor/stickyscroll/StickyScrollingControl.java b/bundles/org.eclipse.ui.editors/src/org/eclipse/ui/internal/texteditor/stickyscroll/StickyScrollingControl.java index 12bb922768e..ed21303fb73 100644 --- a/bundles/org.eclipse.ui.editors/src/org/eclipse/ui/internal/texteditor/stickyscroll/StickyScrollingControl.java +++ b/bundles/org.eclipse.ui.editors/src/org/eclipse/ui/internal/texteditor/stickyscroll/StickyScrollingControl.java @@ -331,7 +331,10 @@ private void calculateAndSetStickyLinesCanvasBounds() { StyledText textWidget= sourceViewer.getTextWidget(); int numberStickyLines= getNumberStickyLines(); - int lineHeight= stickyLineText.getLineHeight() * numberStickyLines; + int lineHeight = 0; + for (int i = 0; i < numberStickyLines; i++) { + lineHeight += stickyLineText.getLineHeight(stickyLineText.getOffsetAtLine(i)); + } int spacingHeight= stickyLineText.getLineSpacing() * (numberStickyLines - 1); int separatorHeight= bottomSeparator.getBounds().height; @@ -450,7 +453,8 @@ private boolean areStickyLinesOutDated(StyledText textWidget) { } private void limitVisibleStickyLinesToTextWidgetHeight(StyledText textWidget) { - int lineHeight= textWidget.getLineHeight() + textWidget.getLineSpacing(); + int topOffset = textWidget.getOffsetAtLine(textWidget.getTopIndex()); + int lineHeight = textWidget.getLineHeight(topOffset) + textWidget.getLineSpacing(); int textWidgetHeight= textWidget.getBounds().height; int visibleLinesInTextWidget= textWidgetHeight / lineHeight; diff --git a/tests/org.eclipse.ui.editors.tests/src/org/eclipse/ui/internal/texteditor/stickyscroll/StickyScrollingControlTest.java b/tests/org.eclipse.ui.editors.tests/src/org/eclipse/ui/internal/texteditor/stickyscroll/StickyScrollingControlTest.java index babf3580e22..d55ab75f6cb 100644 --- a/tests/org.eclipse.ui.editors.tests/src/org/eclipse/ui/internal/texteditor/stickyscroll/StickyScrollingControlTest.java +++ b/tests/org.eclipse.ui.editors.tests/src/org/eclipse/ui/internal/texteditor/stickyscroll/StickyScrollingControlTest.java @@ -17,6 +17,7 @@ import static org.hamcrest.Matchers.greaterThan; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -236,6 +237,33 @@ void testStyling() { assertEquals(hoverColor, stickyLineText.getForeground()); } + @Test + void testCanvasBoundsHeightAdjustsForVariableLineHeights() { + sourceViewer.getTextWidget().setBounds(0, 0, 200, 200); + + // Step 1: Set 2 plain-text sticky lines and record canvas height + List plainLines = List.of(new StickyLineStub("line 1", 0), new StickyLineStub("line 2", 1)); + stickyScrollingControl.setStickyLines(plainLines); + Canvas stickyControlCanvas = getStickyControlCanvas(shell); + int heightWithPlainText = stickyControlCanvas.getBounds().height; + + // Step 2: Replace second sticky line with line requiring space + Font largerFont = new Font(Display.getDefault(), + new FontData(shell.getFont().getFontData()[0].getName(), 40, SWT.NORMAL)); + String bigText = "line 2 big"; //$NON-NLS-1$ + StyleRange bigFontRange = new StyleRange(0, bigText.length(), null, null); + bigFontRange.font = largerFont; + List linesWithLargerFont = List.of(new StickyLineStub("line 1", 0), + new StickyLineStub(bigText, 1, new StyleRange[] { bigFontRange })); + stickyScrollingControl.setStickyLines(linesWithLargerFont); + int heightWithLargerFont = getStickyControlCanvas(shell).getBounds().height; + + assertTrue(heightWithLargerFont > heightWithPlainText, + "Canvas height must increase when one sticky line has a larger font"); //$NON-NLS-1$ + + largerFont.dispose(); + } + @Test void testLayoutStickyLinesCanvasOnResize() { sourceViewer.getTextWidget().setBounds(0, 0, 200, 200);