mirror of
https://github.com/fankes/termux-app.git
synced 2025-09-04 17:55:36 +08:00
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.
This commit is contained in:
committed by
Leonid Pliushch
parent
930029b5d2
commit
f33ebf810f
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user