Support blurred cursor

This commit is contained in:
Daniel Imms
2017-09-01 22:42:31 -07:00
parent b57b94ad0b
commit dc1e727613
7 changed files with 78 additions and 10 deletions
+1
View File
@@ -35,6 +35,7 @@ export interface ITerminal extends IEventEmitter {
options: ITerminalOptions;
buffers: IBufferSet;
buffer: IBuffer;
isFocused: boolean;
/**
* Emit the 'data' event and populate the given data.
+4
View File
@@ -412,6 +412,10 @@ export class Terminal extends EventEmitter implements ITerminal, IInputHandlingT
this.textarea.focus();
}
public get isFocused(): boolean {
return document.activeElement === this.textarea;
}
public setTheme(theme: ITheme): void {
// TODO: Allow setting of theme before renderer is ready
if (this.renderer) {
+14 -2
View File
@@ -30,6 +30,8 @@ export abstract class BaseRenderLayer implements IRenderLayer {
// TODO: Should this do anything?
public onOptionsChanged(terminal: ITerminal): void {}
public onBlur(terminal: ITerminal): void {}
public onFocus(terminal: ITerminal): void {}
public onCursorMove(terminal: ITerminal): void {}
public onGridChanged(terminal: ITerminal, startRow: number, endRow: number): void {}
public onSelectionChanged(terminal: ITerminal, start: [number, number], end: [number, number]): void {}
@@ -58,7 +60,7 @@ export abstract class BaseRenderLayer implements IRenderLayer {
this._ctx.fillRect(startCol * this.scaledCharWidth, startRow * this.scaledCharHeight, colWidth * this.scaledCharWidth, colHeight * this.scaledCharHeight);
}
protected fillBottomLineAtCell(x: number, y: number): void {
protected drawBottomLineAtCell(x: number, y: number): void {
this._ctx.fillRect(
x * this.scaledCharWidth,
(y + 1) * this.scaledCharHeight - window.devicePixelRatio - 1 /* Ensure it's drawn within the cell */,
@@ -66,7 +68,7 @@ export abstract class BaseRenderLayer implements IRenderLayer {
window.devicePixelRatio);
}
protected fillLeftLineAtCell(x: number, y: number): void {
protected drawLeftLineAtCell(x: number, y: number): void {
this._ctx.fillRect(
x * this.scaledCharWidth,
y * this.scaledCharHeight,
@@ -74,6 +76,16 @@ export abstract class BaseRenderLayer implements IRenderLayer {
this.scaledCharHeight);
}
protected drawSquareAtCell(x: number, y: number, color: string): void {
this._ctx.strokeStyle = color;
this._ctx.lineWidth = window.devicePixelRatio;
this._ctx.strokeRect(
x * this.scaledCharWidth + window.devicePixelRatio / 2,
y * this.scaledCharHeight + (window.devicePixelRatio / 2),
this.scaledCharWidth - window.devicePixelRatio,
this.scaledCharHeight - window.devicePixelRatio);
}
protected clearAll(): void {
this._ctx.clearRect(0, 0, this._canvas.width, this._canvas.height);
}
+40 -7
View File
@@ -16,6 +16,7 @@ export class CursorRenderLayer extends BaseRenderLayer {
private _state: [number, number];
private _cursorRenderers: {[key: string]: (terminal: ITerminal, x: number, y: number, charData: CharData) => void};
private _cursorBlinkStateManager: CursorBlinkStateManager;
private _isFocused: boolean;
constructor(container: HTMLElement, zIndex: number, colors: IColorSet) {
super(container, 'cursor', zIndex, colors);
@@ -37,6 +38,20 @@ export class CursorRenderLayer extends BaseRenderLayer {
}
}
public onBlur(terminal: ITerminal): void {
if (this._cursorBlinkStateManager) {
// this._cursorBlinkStateManager.pause();
}
terminal.refresh(terminal.buffer.y, terminal.buffer.y);
}
public onFocus(terminal: ITerminal): void {
if (this._cursorBlinkStateManager) {
// this._cursorBlinkStateManager.resume();
}
terminal.refresh(terminal.buffer.y, terminal.buffer.y);
}
public onOptionsChanged(terminal: ITerminal): void {
if (terminal.options.cursorBlink) {
if (!this._cursorBlinkStateManager) {
@@ -69,11 +84,8 @@ export class CursorRenderLayer extends BaseRenderLayer {
}
private _render(terminal: ITerminal, triggeredByAnimationFrame: boolean): void {
// TODO: Track blur/focus somehow, support unfocused cursor
// Don't draw the cursor if it's hidden
if (!terminal.cursorState ||
terminal.cursorHidden ||
(this._cursorBlinkStateManager && !this._cursorBlinkStateManager.isCursorVisible)) {
if (!terminal.cursorState || terminal.cursorHidden) {
this._clearCursor();
return;
}
@@ -87,6 +99,23 @@ export class CursorRenderLayer extends BaseRenderLayer {
return;
}
const charData = terminal.buffer.lines.get(cursorY)[terminal.buffer.x];
if (!terminal.isFocused) {
this._clearCursor();
this._ctx.save();
this._ctx.fillStyle = this.colors.ansi[COLOR_CODES.WHITE];
this._renderBlurCursor(terminal, terminal.buffer.x, viewportRelativeCursorY, charData);
this._ctx.restore();
return;
}
// Don't draw the cursor if it's blinking
if (this._cursorBlinkStateManager && !this._cursorBlinkStateManager.isCursorVisible) {
this._clearCursor();
return;
}
if (this._state) {
// The cursor is already in the correct spot, don't redraw
if (this._state[0] === terminal.buffer.x && this._state[1] === viewportRelativeCursorY) {
@@ -95,7 +124,6 @@ export class CursorRenderLayer extends BaseRenderLayer {
this._clearCursor();
}
const charData = terminal.buffer.lines.get(cursorY)[terminal.buffer.x];
this._ctx.save();
this._ctx.fillStyle = this.colors.ansi[COLOR_CODES.WHITE];
this._cursorRenderers[terminal.options.cursorStyle || 'block'](terminal, terminal.buffer.x, viewportRelativeCursorY, charData);
@@ -111,7 +139,7 @@ export class CursorRenderLayer extends BaseRenderLayer {
}
private _renderBarCursor(terminal: ITerminal, x: number, y: number, charData: CharData): void {
this.fillLeftLineAtCell(x, y);
this.drawLeftLineAtCell(x, y);
}
private _renderBlockCursor(terminal: ITerminal, x: number, y: number, charData: CharData): void {
@@ -120,7 +148,12 @@ export class CursorRenderLayer extends BaseRenderLayer {
}
private _renderUnderlineCursor(terminal: ITerminal, x: number, y: number, charData: CharData): void {
this.fillBottomLineAtCell(x, y);
this.drawBottomLineAtCell(x, y);
}
private _renderBlurCursor(terminal: ITerminal, x: number, y: number, charData: CharData): void {
// TODO: Support cursor colors
this.drawSquareAtCell(x, y, this.colors.foreground);
}
}
+1 -1
View File
@@ -97,7 +97,7 @@ export class ForegroundRenderLayer extends BaseRenderLayer {
} else {
this._ctx.fillStyle = this.colors.foreground;
}
this.fillBottomLineAtCell(x, y);
this.drawBottomLineAtCell(x, y);
}
this.drawChar(terminal, char, code, x, y, fg);
+10
View File
@@ -1,6 +1,16 @@
import { ITerminal, ITerminalOptions } from '../Interfaces';
export interface IRenderLayer {
/**
* Called when the terminal loses focus.
*/
onBlur(terminal: ITerminal): void;
/**
* * Called when the terminal gets focus.
*/
onFocus(terminal: ITerminal): void;
/**
* Called when the cursor is moved.
*/
+8
View File
@@ -57,6 +57,14 @@ export class Renderer {
this._renderLayers.forEach(l => l.resize(this._terminal, width, height, true));
}
public onBlur(): void {
this._renderLayers.forEach(l => l.onBlur(this._terminal));
}
public onFocus(): void {
this._renderLayers.forEach(l => l.onFocus(this._terminal));
}
public onSelectionChanged(start: [number, number], end: [number, number]): void {
this._renderLayers.forEach(l => l.onSelectionChanged(this._terminal, start, end));
}