From f33ebf810f9fb62931c07eca8134335fcc92ed99 Mon Sep 17 00:00:00 2001 From: Danny Lin Date: Fri, 3 Jul 2020 21:08:36 -0700 Subject: [PATCH] Fix selection rendering with alternate cursor styles There is currently a bug where selection rendering is broken if the active cursor shape is anything other than the default solid box. Selected text is normally highlighted by effectively rendering a cursor over all of the characters in the selection region, but if the cursor is a bar, the resulting selection highlight is too narrow to cover the full width of the selection. Similarly, if the cursor is an underline, all of the selected text will be underlined instead of highlighted. To fix this issue, treat selections different from cursors in the rendering logic and force the renderer to always use the block cursor style for rendering selections. That way, we get correct behavior regardless of what the current cursor shape is. --- .../java/com/termux/view/TerminalRenderer.java | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/terminal-view/src/main/java/com/termux/view/TerminalRenderer.java b/terminal-view/src/main/java/com/termux/view/TerminalRenderer.java index 8c12ad55..7a182441 100644 --- a/terminal-view/src/main/java/com/termux/view/TerminalRenderer.java +++ b/terminal-view/src/main/java/com/termux/view/TerminalRenderer.java @@ -86,6 +86,7 @@ public final class TerminalRenderer { long lastRunStyle = 0; boolean lastRunInsideCursor = false; + boolean lastRunInsideSelection = false; int lastRunStartColumn = -1; int lastRunStartIndex = 0; boolean lastRunFontWidthMismatch = false; @@ -98,7 +99,8 @@ public final class TerminalRenderer { final int charsForCodePoint = charIsHighsurrogate ? 2 : 1; final int codePoint = charIsHighsurrogate ? Character.toCodePoint(charAtIndex, line[currentCharIndex + 1]) : charAtIndex; final int codePointWcWidth = WcWidth.width(codePoint); - final boolean insideCursor = (column >= selx1 && column <= selx2) || (cursorX == column || (codePointWcWidth == 2 && cursorX == column + 1)); + final boolean insideCursor = (cursorX == column || (codePointWcWidth == 2 && cursorX == column + 1)); + final boolean insideSelection = column >= selx1 && column <= selx2; final long style = lineObject.getStyle(column); // Check if the measured text width for this code point is not the same as that expected by wcwidth(). @@ -109,20 +111,22 @@ public final class TerminalRenderer { currentCharIndex, charsForCodePoint); final boolean fontWidthMismatch = Math.abs(measuredCodePointWidth / mFontWidth - codePointWcWidth) > 0.01; - if (style != lastRunStyle || insideCursor != lastRunInsideCursor || fontWidthMismatch || lastRunFontWidthMismatch) { + if (style != lastRunStyle || insideCursor != lastRunInsideCursor || insideSelection != lastRunInsideSelection || fontWidthMismatch || lastRunFontWidthMismatch) { if (column == 0) { // Skip first column as there is nothing to draw, just record the current style. } else { final int columnWidthSinceLastRun = column - lastRunStartColumn; final int charsSinceLastRun = currentCharIndex - lastRunStartIndex; - int cursorColor = lastRunInsideCursor ? mEmulator.mColors.mCurrentColors[TextStyle.COLOR_INDEX_CURSOR] : 0; + int cursorColor = (lastRunInsideCursor || lastRunInsideSelection) ? mEmulator.mColors.mCurrentColors[TextStyle.COLOR_INDEX_CURSOR] : 0; + int cursorStyle = lastRunInsideSelection ? TerminalEmulator.CURSOR_STYLE_BLOCK : cursorShape; drawTextRun(canvas, line, palette, heightOffset, lastRunStartColumn, columnWidthSinceLastRun, lastRunStartIndex, charsSinceLastRun, measuredWidthForRun, - cursorColor, cursorShape, lastRunStyle, reverseVideo); + cursorColor, cursorStyle, lastRunStyle, reverseVideo); } measuredWidthForRun = 0.f; lastRunStyle = style; lastRunInsideCursor = insideCursor; + lastRunInsideSelection = insideSelection; lastRunStartColumn = column; lastRunStartIndex = currentCharIndex; lastRunFontWidthMismatch = fontWidthMismatch; @@ -139,9 +143,10 @@ public final class TerminalRenderer { final int columnWidthSinceLastRun = columns - lastRunStartColumn; final int charsSinceLastRun = currentCharIndex - lastRunStartIndex; - int cursorColor = lastRunInsideCursor ? mEmulator.mColors.mCurrentColors[TextStyle.COLOR_INDEX_CURSOR] : 0; + int cursorColor = (lastRunInsideCursor || lastRunInsideSelection) ? mEmulator.mColors.mCurrentColors[TextStyle.COLOR_INDEX_CURSOR] : 0; + int cursorStyle = lastRunInsideSelection ? TerminalEmulator.CURSOR_STYLE_BLOCK : cursorShape; drawTextRun(canvas, line, palette, heightOffset, lastRunStartColumn, columnWidthSinceLastRun, lastRunStartIndex, charsSinceLastRun, - measuredWidthForRun, cursorColor, cursorShape, lastRunStyle, reverseVideo); + measuredWidthForRun, cursorColor, cursorStyle, lastRunStyle, reverseVideo); } }