Skip to content

Commit a5646a5

Browse files
authored
Merge pull request xtermjs#4801 from tisilent/fix-inactive-cursor-spot
using viewport relative coordinate
2 parents 86074c9 + 8a1790d commit a5646a5

File tree

2 files changed

+46
-3
lines changed

2 files changed

+46
-3
lines changed

addons/addon-webgl/src/WebglRenderer.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -391,6 +391,7 @@ export class WebglRenderer extends Disposable implements IRenderer {
391391
end = clamp(end, terminal.rows - 1, 0);
392392

393393
const cursorY = this._terminal.buffer.active.baseY + this._terminal.buffer.active.cursorY;
394+
const viewportRelativeCursorY = cursorY - terminal.buffer.ydisp;
394395
// in case cursor.x == cols adjust visual cursor to cols - 1
395396
const cursorX = Math.min(this._terminal.buffer.active.cursorX, terminal.cols - 1);
396397
let lastCursorX = -1;
@@ -449,7 +450,7 @@ export class WebglRenderer extends Disposable implements IRenderer {
449450
if (x === cursorX) {
450451
this._model.cursor = {
451452
x: cursorX,
452-
y: this._terminal.buffer.active.cursorY,
453+
y: viewportRelativeCursorY,
453454
width: cell.getWidth(),
454455
style: this._coreBrowserService.isFocused ?
455456
(terminal.options.cursorStyle || 'block') : terminal.options.cursorInactiveStyle,

test/playwright/SharedRendererTests.ts

+44-2
Original file line numberDiff line numberDiff line change
@@ -1171,9 +1171,35 @@ export function injectSharedRendererTests(ctx: ISharedRendererTestContext): void
11711171
await ctx.value.proxy.selectAll();
11721172
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 1, 1), [0, 0, 255, 255]);
11731173
});
1174+
test('#4799: cursor should be in the correct position', async () => {
1175+
const theme: ITheme = {
1176+
cursor: '#0000FF'
1177+
};
1178+
await ctx.value.page.evaluate(`window.term.options.theme = ${JSON.stringify(theme)};`);
1179+
for (let index = 0; index < 160; index++) {
1180+
await ctx.value.proxy.writeln(``);
1181+
}
1182+
await ctx.value.proxy.focus();
1183+
await ctx.value.proxy.write('\x1b[A');
1184+
await ctx.value.proxy.write('\x1b[A');
1185+
await ctx.value.proxy.scrollLines(-2);
1186+
const rows = await ctx.value.proxy.rows;
1187+
// block cursor style
1188+
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 1, rows), [0, 0, 255, 255]);
1189+
await ctx.value.proxy.blur();
1190+
frameDetails = undefined;
1191+
// outlink cursor style
1192+
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 1, rows), [0, 0, 0, 255]);
1193+
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 1, rows, CellColorPosition.FIRST), [0, 0, 255, 255]);
1194+
});
11741195
});
11751196
}
11761197

1198+
enum CellColorPosition {
1199+
CENTER = 0,
1200+
FIRST = 1
1201+
}
1202+
11771203
/**
11781204
* Injects shared renderer tests where it's required to re-initialize the terminal for each test.
11791205
* This is much slower than just calling `Terminal.reset` but testing some features needs this
@@ -1214,11 +1240,16 @@ export function injectSharedRendererTestsStandalone(ctx: ISharedRendererTestCont
12141240
* @param col The 1-based column index to get the color for.
12151241
* @param row The 1-based row index to get the color for.
12161242
*/
1217-
function getCellColor(ctx: ITestContext, col: number, row: number): MaybeAsync<[red: number, green: number, blue: number, alpha: number]> {
1243+
function getCellColor(ctx: ITestContext, col: number, row: number, position: CellColorPosition = CellColorPosition.CENTER): MaybeAsync<[red: number, green: number, blue: number, alpha: number]> {
12181244
if (!frameDetails) {
12191245
return getFrameDetails(ctx).then(frameDetails => getCellColorInner(frameDetails, col, row));
12201246
}
1221-
return getCellColorInner(frameDetails, col, row);
1247+
switch (position) {
1248+
case CellColorPosition.CENTER:
1249+
return getCellColorInner(frameDetails, col, row);
1250+
case CellColorPosition.FIRST:
1251+
return getCellColorFirstPoint(frameDetails, col, row);
1252+
}
12221253
}
12231254

12241255
let frameDetails: { cols: number, rows: number, decoded: IImage32 } | undefined = undefined;
@@ -1244,6 +1275,17 @@ function getCellColorInner(frameDetails: { cols: number, rows: number, decoded:
12441275
return Array.from(frameDetails.decoded.data.slice(i, i + 4)) as [number, number, number, number];
12451276
}
12461277

1278+
function getCellColorFirstPoint(frameDetails: { cols: number, rows: number, decoded: IImage32 }, col: number, row: number): [red: number, green: number, blue: number, alpha: number] {
1279+
const cellSize = {
1280+
width: frameDetails.decoded.width / frameDetails.cols,
1281+
height: frameDetails.decoded.height / frameDetails.rows
1282+
};
1283+
const x = Math.floor((col - 1/* 1- to 0-based index */) * cellSize.width);
1284+
const y = Math.floor((row - 1/* 1- to 0-based index */) * cellSize.height);
1285+
const i = (y * frameDetails.decoded.width + x) * 4/* 4 channels per pixel */;
1286+
return Array.from(frameDetails.decoded.data.slice(i, i + 4)) as [number, number, number, number];
1287+
}
1288+
12471289
const COLORS_16_TO_255 = [
12481290
'#000000', '#00005f', '#000087', '#0000af', '#0000d7', '#0000ff', '#005f00', '#005f5f', '#005f87', '#005faf', '#005fd7', '#005fff', '#008700', '#00875f', '#008787', '#0087af',
12491291
'#0087d7', '#0087ff', '#00af00', '#00af5f', '#00af87', '#00afaf', '#00afd7', '#00afff', '#00d700', '#00d75f', '#00d787', '#00d7af', '#00d7d7', '#00d7ff', '#00ff00', '#00ff5f',

0 commit comments

Comments
 (0)