提交 4d718464 编写于 作者: D Daniel Imms 提交者: Alex Dima

Rendering improvements

上级 8b034f10
......@@ -264,6 +264,11 @@ configurationRegistry.registerConfiguration({
type: 'boolean',
default: true
},
'terminal.integrated.enableLatencyMitigation': {
description: nls.localize('terminal.integrated.enableLatencyMitigation', "Whether to enable the latency mitigation feature for high-latency terminals."),
type: 'boolean',
default: false
},
'terminal.integrated.experimentalRefreshOnResume': {
description: nls.localize('terminal.integrated.experimentalRefreshOnResume', "An experimental setting that will refresh the terminal renderer when the system is resumed."),
type: 'boolean',
......
......@@ -587,6 +587,19 @@ export class TerminalInstance implements ITerminalInstance {
if (this._processManager) {
this._widgetManager = new TerminalWidgetManager(this._wrapperElement);
this._processManager.onProcessReady(() => this._linkHandler.setWidgetManager(this._widgetManager));
this._processManager.onProcessReady(() => {
if (this._configHelper.config.enableLatencyMitigation) {
if (!this._processManager) {
return;
}
this._processManager.getLatency().then(latency => {
if (latency > 20 && (this._xterm as any).typeAheadInit) {
(this._xterm as any).typeAheadInit(this._processManager, this._themeService);
}
});
}
});
}
const computedStyle = window.getComputedStyle(this._container);
......
......@@ -6,7 +6,7 @@
import * as platform from 'vs/base/common/platform';
import * as terminalEnvironment from 'vs/workbench/contrib/terminal/common/terminalEnvironment';
import { IDisposable } from 'vs/base/common/lifecycle';
import { ProcessState, ITerminalProcessManager, IShellLaunchConfig, ITerminalConfigHelper, ITerminalChildProcess } from 'vs/workbench/contrib/terminal/common/terminal';
import { ProcessState, ITerminalProcessManager, IShellLaunchConfig, ITerminalConfigHelper, ITerminalChildProcess, IBeforeProcessDataEvent } from 'vs/workbench/contrib/terminal/common/terminal';
import { ILogService } from 'vs/platform/log/common/log';
import { Emitter, Event } from 'vs/base/common/event';
import { IHistoryService } from 'vs/workbench/services/history/common/history';
......@@ -56,6 +56,8 @@ export class TerminalProcessManager implements ITerminalProcessManager {
private readonly _onProcessReady = new Emitter<void>();
public get onProcessReady(): Event<void> { return this._onProcessReady.event; }
private readonly _onBeforeProcessData = new Emitter<IBeforeProcessDataEvent>();
public get onBeforeProcessData(): Event<IBeforeProcessDataEvent> { return this._onBeforeProcessData.event; }
private readonly _onProcessData = new Emitter<string>();
public get onProcessData(): Event<string> { return this._onProcessData.event; }
private readonly _onProcessTitle = new Emitter<string>();
......@@ -181,7 +183,11 @@ export class TerminalProcessManager implements ITerminalProcessManager {
const p = this._process!;
p.onProcessData(data => {
this._onProcessData.fire(data);
const beforeProcessDataEvent: IBeforeProcessDataEvent = { data };
this._onBeforeProcessData.fire(beforeProcessDataEvent);
if (beforeProcessDataEvent.data && beforeProcessDataEvent.data.length > 0) {
this._onProcessData.fire(beforeProcessDataEvent.data);
}
});
p.onProcessIdReady(pid => {
......
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { Terminal as XTermTerminal } from 'vscode-xterm';
import { ITerminalProcessManager } from 'vs/workbench/contrib/terminal/common/terminal';
import { IThemeService } from 'vs/platform/theme/common/themeService';
export interface ITerminalCore {
buffer: any;
}
export interface ITypeAheadAddonTerminal {
_core: ITerminalCore;
on: any;
write(data: string): void;
cols: number;
__typeAheadQueue: string[];
__typeAheadState: TypeAheadState;
__typeAheadCurrentYBase: number;
__typeAheadCurrentY: number;
}
enum TypeAheadState {
/**
* The normal state, ready to type if it starts.
*/
Normal,
/**
* Something happens such that we cannot make a good guess on what to print,
* wait until the cursor row changes before proceeding.
*/
AwaitingRowChange
}
function isCharPrintable(data: string): boolean {
const code = data.charCodeAt(0);
return data.length === 1 && code >= 32 && code <= 126;
}
function init(terminal: any, processManager: ITerminalProcessManager, themeService: IThemeService): void {
const t = terminal as ITypeAheadAddonTerminal;
t.__typeAheadQueue = [];
t.__typeAheadState = TypeAheadState.Normal;
t.__typeAheadCurrentYBase = 0;
t.__typeAheadCurrentY = 0;
function typeAhead(data: string): void {
for (let i = 0; i < data.length; i++) {
t.__typeAheadQueue.push(data[i]);
}
t.write(data);
}
t.on('cursormove', () => {
// Reset if the cursor row changed
if (t._core.buffer.ybase !== t.__typeAheadCurrentYBase || t._core.buffer.y !== t.__typeAheadCurrentY) {
t.__typeAheadCurrentYBase = t._core.buffer.ybase;
t.__typeAheadCurrentY = t._core.buffer.y;
t.__typeAheadState = TypeAheadState.Normal;
}
});
t.on('data', (data: string) => {
// Exit if we're waiting for a row change
if (t.__typeAheadState === TypeAheadState.AwaitingRowChange) {
return;
}
// Only enable in the normal buffer
if (!t._core.buffer._hasScrollback) {
return;
}
// // Handle enter
// if (data === '\r') {
// typeAhead('\r\n');
// return;
// }
// // Left arrow
// if (data === '\x1b[D') {
// // TODO: How to stop it from going beyond prompt?
// typeAhead(String.fromCharCode(8));
// }
// // Right arrow
// if (data === '\x1b[C') {
// // TODO: How to stop it from going beyond prompt?
// typeAhead('\x1b[C');
// }
// // Backspace (DEL)
// if (data.charCodeAt(0) === 127) {
// // TODO: This would require knowing the prompt length to be able to shift everything
// }
if (!isCharPrintable(data)) {
t.__typeAheadState = TypeAheadState.AwaitingRowChange;
return;
}
if (t._core.buffer.x === t.cols - 1) {
// TODO: Does the space get added on Windows/Linux too?
data += ' \r';
}
typeAhead(data);
});
processManager.onBeforeProcessData(event => {
let consumeCount = 0;
for (let i = 0; i < event.data.length; i++) {
if (t.__typeAheadQueue[0] === event.data[i]) {
t.__typeAheadQueue.shift();
consumeCount++;
} else {
t.__typeAheadQueue.length = 0;
break;
}
}
if (consumeCount === event.data.length) {
event.data = '';
} else if (consumeCount > 0) {
event.data = event.data.substr(consumeCount);
}
});
}
export function apply(terminalConstructor: typeof XTermTerminal) {
(<any>terminalConstructor.prototype).typeAheadInit = function (processManager: ITerminalProcessManager, themeService: IThemeService): void {
init(this, processManager, themeService);
};
}
\ No newline at end of file
......@@ -101,6 +101,7 @@ export interface ITerminalConfiguration {
experimentalBufferImpl: 'JsArray' | 'TypedArray';
splitCwd: 'workspaceRoot' | 'initial' | 'inherited';
windowsEnableConpty: boolean;
enableLatencyMitigation: boolean;
experimentalRefreshOnResume: boolean;
}
......@@ -634,6 +635,14 @@ export interface ITerminalCommandTracker {
selectToNextLine(): void;
}
export interface IBeforeProcessDataEvent {
/**
* The data of the event, this can be modified by the event listener to change what gets sent
* to the terminal.
*/
data: string;
}
export interface ITerminalProcessManager extends IDisposable {
readonly processState: ProcessState;
readonly ptyProcessReady: Promise<void>;
......@@ -643,6 +652,7 @@ export interface ITerminalProcessManager extends IDisposable {
readonly userHome: string | undefined;
readonly onProcessReady: Event<void>;
readonly onBeforeProcessData: Event<IBeforeProcessDataEvent>;
readonly onProcessData: Event<string>;
readonly onProcessTitle: Event<string>;
readonly onProcessExit: Event<number>;
......
......@@ -12,6 +12,7 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti
import { TerminalProcessManager } from 'vs/workbench/contrib/terminal/browser/terminalProcessManager';
import { IProcessEnvironment } from 'vs/base/common/platform';
import { TerminalProcess } from 'vs/workbench/contrib/terminal/node/terminalProcess';
import * as typeAheadAddon from 'vs/workbench/contrib/terminal/browser/terminalTypeAheadAddon';
let Terminal: typeof XTermTerminal;
......@@ -35,6 +36,7 @@ export class TerminalInstanceService implements ITerminalInstanceService {
Terminal.applyAddon(require.__$__nodeRequire('vscode-xterm/lib/addons/search/search'));
Terminal.applyAddon(require.__$__nodeRequire('vscode-xterm/lib/addons/webLinks/webLinks'));
Terminal.applyAddon(require.__$__nodeRequire('vscode-xterm/lib/addons/winptyCompat/winptyCompat'));
Terminal.applyAddon(typeAheadAddon);
// Localize strings
Terminal.strings.blankLine = nls.localize('terminal.integrated.a11yBlankLine', 'Blank line');
Terminal.strings.promptLabel = nls.localize('terminal.integrated.a11yPromptLabel', 'Terminal input');
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册