Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

terminal: bump xterm and addons #12691

Merged
merged 4 commits into from
Feb 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,8 @@

- [deps] bumped supported Node.js version from 16.x to >=18, you may need to update your environments [#12711](https://github.com/eclipse-theia/theia/pull/12711)
- [preferences] removed the `welcome.alwaysShowWelcomePage` preference in favor of `workbench.startupEditor` [#12813](https://github.com/eclipse-theia/theia/pull/12813)
- [terminal] deprecated `terminal.integrated.rendererType` preference [#12691](https://github.com/eclipse-theia/theia/pull/12691)
- [terminal] removed protected method `TerminalWidgetImpl.getTerminalRendererType` [#12691](https://github.com/eclipse-theia/theia/pull/12691)

## v1.40.0 - 07/27/2023

Expand Down
8 changes: 4 additions & 4 deletions packages/terminal/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@
"@theia/process": "1.46.0",
"@theia/variable-resolver": "1.46.0",
"@theia/workspace": "1.46.0",
"xterm": "^4.16.0",
"xterm-addon-fit": "^0.5.0",
"xterm-addon-search": "^0.8.2"
"xterm": "^5.3.0",
"xterm-addon-fit": "^0.8.0",
"xterm-addon-search": "^0.13.0"
},
"publishConfig": {
"access": "public"
Expand Down Expand Up @@ -53,4 +53,4 @@
"nyc": {
"extends": "../../configs/nyc.json"
}
}
}
22 changes: 22 additions & 0 deletions packages/terminal/src/browser/terminal-frontend-contribution.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ import { nls } from '@theia/core/lib/common/nls';
import { Profiles, TerminalPreferences } from './terminal-preferences';
import { ShellTerminalProfile } from './shell-terminal-profile';
import { VariableResolverService } from '@theia/variable-resolver/lib/browser';
import { Color } from '@theia/core/lib/common/color';

export namespace TerminalMenus {
export const TERMINAL = [...MAIN_MENU_BAR, '7_terminal'];
Expand Down Expand Up @@ -1074,6 +1075,27 @@ export class TerminalFrontendContribution implements FrontendApplicationContribu
},
description: 'The selection background color of the terminal.'
});
colors.register({
id: 'terminal.inactiveSelectionBackground',
defaults: {
light: Color.transparent('terminal.selectionBackground', 0.5),
dark: Color.transparent('terminal.selectionBackground', 0.5),
hcDark: Color.transparent('terminal.selectionBackground', 0.7),
hcLight: Color.transparent('terminal.selectionBackground', 0.5),
},
description: 'The selection background color of the terminal when it does not have focus.'
});
colors.register({
id: 'terminal.selectionForeground',
defaults: {
light: undefined,
dark: undefined,
hcDark: '#000000',
hcLight: '#ffffff'
},
// eslint-disable-next-line max-len
description: 'The selection foreground color of the terminal. When this is null the selection foreground will be retained and have the minimum contrast ratio feature applied.'
});
colors.register({
id: 'terminal.border',
defaults: {
Expand Down
3 changes: 2 additions & 1 deletion packages/terminal/src/browser/terminal-preferences.ts
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,8 @@ export const TerminalConfigSchema: PreferenceSchema = {
description: nls.localize('theia/terminal/rendererType', 'Controls how the terminal is rendered.'),
type: 'string',
enum: ['canvas', 'dom'],
default: 'canvas'
default: 'canvas',
deprecationMessage: nls.localize('theia/terminal/rendererTypeDeprecationMessage', 'The renderer type is no longer supported as an option.')
},
'terminal.integrated.copyOnSelection': {
description: nls.localizeByDefault('Controls whether text selected in the terminal will be copied to the clipboard.'),
Expand Down
8 changes: 6 additions & 2 deletions packages/terminal/src/browser/terminal-theme-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -187,14 +187,18 @@ export class TerminalThemeService {
const backgroundColor = this.colorRegistry.getCurrentColor('terminal.background') || this.colorRegistry.getCurrentColor('panel.background');
const cursorColor = this.colorRegistry.getCurrentColor('terminalCursor.foreground') || foregroundColor;
const cursorAccentColor = this.colorRegistry.getCurrentColor('terminalCursor.background') || backgroundColor;
const selectionColor = this.colorRegistry.getCurrentColor('terminal.selectionBackground');
const selectionBackgroundColor = this.colorRegistry.getCurrentColor('terminal.selectionBackground');
const selectionInactiveBackground = this.colorRegistry.getCurrentColor('terminal.inactiveSelectionBackground');
const selectionForegroundColor = this.colorRegistry.getCurrentColor('terminal.selectionForeground');

const theme: ITheme = {
background: backgroundColor,
foreground: foregroundColor,
cursor: cursorColor,
cursorAccent: cursorAccentColor,
selection: selectionColor
selectionBackground: selectionBackgroundColor,
selectionInactiveBackground: selectionInactiveBackground,
selectionForeground: selectionForegroundColor
};
// eslint-disable-next-line guard-for-in
for (const id in terminalAnsiColorMap) {
Expand Down
123 changes: 63 additions & 60 deletions packages/terminal/src/browser/terminal-widget-impl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
// *****************************************************************************

import { Terminal, RendererType } from 'xterm';
import { Terminal } from 'xterm';
import { FitAddon } from 'xterm-addon-fit';
import { inject, injectable, named, postConstruct } from '@theia/core/shared/inversify';
import { ContributionProvider, Disposable, Event, Emitter, ILogger, DisposableCollection, Channel, OS } from '@theia/core';
Expand All @@ -32,7 +32,7 @@ import {
TerminalLocation
} from './base/terminal-widget';
import { Deferred } from '@theia/core/lib/common/promise-util';
import { TerminalPreferences, TerminalRendererType, isTerminalRendererType, DEFAULT_TERMINAL_RENDERER_TYPE, CursorStyle } from './terminal-preferences';
import { TerminalPreferences } from './terminal-preferences';
import URI from '@theia/core/lib/common/uri';
import { TerminalService } from './base/terminal-service';
import { TerminalSearchWidgetFactory, TerminalSearchWidget } from './search/terminal-search-widget';
Expand Down Expand Up @@ -161,7 +161,7 @@ export class TerminalWidgetImpl extends TerminalWidget implements StatefulWidget

this.term = new Terminal({
cursorBlink: this.preferences['terminal.integrated.cursorBlinking'],
cursorStyle: this.getCursorStyle(),
cursorStyle: this.preferences['terminal.integrated.cursorStyle'] === 'line' ? 'bar' : this.preferences['terminal.integrated.cursorStyle'],
cursorWidth: this.preferences['terminal.integrated.cursorWidth'],
fontFamily: this.preferences['terminal.integrated.fontFamily'],
fontSize: this.preferences['terminal.integrated.fontSize'],
Expand All @@ -172,7 +172,6 @@ export class TerminalWidgetImpl extends TerminalWidget implements StatefulWidget
lineHeight: this.preferences['terminal.integrated.lineHeight'],
scrollback: this.preferences['terminal.integrated.scrollback'],
fastScrollSensitivity: this.preferences['terminal.integrated.fastScrollSensitivity'],
rendererType: this.getTerminalRendererType(this.preferences['terminal.integrated.rendererType']),
theme: this.themeService.theme
});

Expand All @@ -182,34 +181,12 @@ export class TerminalWidgetImpl extends TerminalWidget implements StatefulWidget
this.initializeLinkHover();

this.toDispose.push(this.preferences.onPreferenceChanged(change => {
const lastSeparator = change.preferenceName.lastIndexOf('.');
if (lastSeparator > 0) {
let preferenceName = change.preferenceName.substring(lastSeparator + 1);
let preferenceValue = change.newValue;

if (preferenceName === 'rendererType') {
const newRendererType = preferenceValue as string;
if (newRendererType !== this.getTerminalRendererType(newRendererType)) {
// Given terminal renderer type is not supported or invalid
preferenceValue = DEFAULT_TERMINAL_RENDERER_TYPE;
}
} else if (preferenceName === 'cursorBlinking') {
// Convert the terminal preference into a valid `xterm` option
preferenceName = 'cursorBlink';
} else if (preferenceName === 'cursorStyle') {
preferenceValue = this.getCursorStyle();
}
try {
this.term.setOption(preferenceName, preferenceValue);
} catch (e) {
console.debug(`xterm configuration: '${preferenceName}' with value '${preferenceValue}' is not valid.`);
}
this.needsResize = true;
this.update();
}
this.updateConfig();
this.needsResize = true;
this.update();
}));

this.toDispose.push(this.themeService.onDidChange(() => this.term.setOption('theme', this.themeService.theme)));
this.toDispose.push(this.themeService.onDidChange(() => this.term.options.theme = this.themeService.theme));
this.attachCustomKeyEventHandler();
const titleChangeListenerDispose = this.term.onTitleChange((title: string) => {
if (this.options.useServerTitle) {
Expand Down Expand Up @@ -314,25 +291,38 @@ export class TerminalWidgetImpl extends TerminalWidget implements StatefulWidget
return this.terminalKind;
}

/**
* Get the cursor style compatible with `xterm`.
* @returns CursorStyle
*/
private getCursorStyle(): CursorStyle {
const value = this.preferences['terminal.integrated.cursorStyle'];
return value === 'line' ? 'bar' : value;
updateConfig(): void {
this.setCursorBlink(this.preferences.get('terminal.integrated.cursorBlinking'));
this.setCursorStyle(this.preferences.get('terminal.integrated.cursorStyle'));
this.setCursorWidth(this.preferences.get('terminal.integrated.cursorWidth'));
this.term.options.fontFamily = this.preferences.get('terminal.integrated.fontFamily');
this.term.options.fontSize = this.preferences.get('terminal.integrated.fontSize');
this.term.options.fontWeight = this.preferences.get('terminal.integrated.fontWeight');
this.term.options.fontWeightBold = this.preferences.get('terminal.integrated.fontWeightBold');
this.term.options.drawBoldTextInBrightColors = this.preferences.get('terminal.integrated.drawBoldTextInBrightColors');
this.term.options.letterSpacing = this.preferences.get('terminal.integrated.letterSpacing');
this.term.options.lineHeight = this.preferences.get('terminal.integrated.lineHeight');
this.term.options.scrollback = this.preferences.get('terminal.integrated.scrollback');
this.term.options.fastScrollSensitivity = this.preferences.get('terminal.integrated.fastScrollSensitivity');
}

/**
* Returns given renderer type if it is valid and supported or default renderer otherwise.
*
* @param terminalRendererType desired terminal renderer type
*/
private getTerminalRendererType(terminalRendererType?: string | TerminalRendererType): RendererType {
if (terminalRendererType && isTerminalRendererType(terminalRendererType)) {
return terminalRendererType;
private setCursorBlink(blink: boolean): void {
if (this.term.options.cursorBlink !== blink) {
this.term.options.cursorBlink = blink;
this.term.refresh(0, this.term.rows - 1);
}
}

private setCursorStyle(style: 'block' | 'underline' | 'bar' | 'line'): void {
if (this.term.options.cursorStyle !== style) {
this.term.options.cursorStyle = (style === 'line') ? 'bar' : style;
}
}

private setCursorWidth(width: number): void {
if (this.term.options.cursorWidth !== width) {
this.term.options.cursorWidth = width;
}
return DEFAULT_TERMINAL_RENDERER_TYPE;
}

protected initializeLinkHover(): void {
Expand Down Expand Up @@ -670,16 +660,34 @@ export class TerminalWidgetImpl extends TerminalWidget implements StatefulWidget
}
this.term.open(this.node);

interface ViewportType {
register(d: Disposable): void;
_refreshAnimationFrame: number | null;
_coreBrowserService: {
window: Window;
}
}

// Workaround for https://github.com/xtermjs/xterm.js/issues/4775. Can be removed for releases > 5.3.0
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const viewPort: ViewportType = (this.term as any)._core.viewport;
viewPort.register(Disposable.create(() => {
if (typeof viewPort._refreshAnimationFrame === 'number') {
viewPort._coreBrowserService.window.cancelAnimationFrame(viewPort._refreshAnimationFrame);
}
}));

if (isFirefox) {
// monkey patching intersection observer handling for secondary window support
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const renderService: any = (this.term as any)._core._renderService;
const originalFunc: (entry: IntersectionObserverEntry) => void = renderService._onIntersectionChange.bind(renderService);

const originalFunc: (entry: IntersectionObserverEntry) => void = renderService._handleIntersectionChange.bind(renderService);
const replacement = function (entry: IntersectionObserverEntry): void {
if (entry.target.ownerDocument !== document) {
// in Firefox, the intersection observer always reports the widget as non-intersecting if the dom element
// is in a different document from when the IntersectionObserver started observing. Since we know
// that the widget is always "visible" when in a secondary window, so we mark the entry as "intersecting"
// that the widget is always "visible" when in a secondary window, so we refresh the rows ourselves
const patchedEvent: IntersectionObserverEntry = {
...entry,
isIntersecting: true,
Expand All @@ -690,21 +698,14 @@ export class TerminalWidgetImpl extends TerminalWidget implements StatefulWidget
}
};

renderService._onIntersectionChange = replacement;
renderService._handleIntersectionChange = replacement.bind(renderService);
}

if (this.initialData) {
this.term.write(this.initialData);
}
this.termOpened = true;
this.initialData = '';

if (isFirefox) {
// The software scrollbars don't work with xterm.js, so we disable the scrollbar if we are on firefox.
if (this.term.element) {
(this.term.element.children.item(0) as HTMLElement).style.overflow = 'hidden';
}
}
}

write(data: string): void {
Expand Down Expand Up @@ -792,11 +793,13 @@ export class TerminalWidgetImpl extends TerminalWidget implements StatefulWidget
return;
}
const geo = this.fitAddon.proposeDimensions();
const cols = geo.cols;
const rows = geo.rows - 1; // subtract one row for margin
this.term.resize(cols, rows);
if (geo) {
const cols = geo.cols;
const rows = geo.rows - 1; // subtract one row for margin
this.term.resize(cols, rows);

this.resizeTerminalProcess();
this.resizeTerminalProcess();
}
}

protected resizeTerminalProcess(): void {
Expand Down
18 changes: 14 additions & 4 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -12134,16 +12134,26 @@ xterm-addon-fit@^0.5.0:
resolved "https://registry.yarnpkg.com/xterm-addon-fit/-/xterm-addon-fit-0.5.0.tgz#2d51b983b786a97dcd6cde805e700c7f913bc596"
integrity sha512-DsS9fqhXHacEmsPxBJZvfj2la30Iz9xk+UKjhQgnYNkrUIN5CYLbw7WEfz117c7+S86S/tpHPfvNxJsF5/G8wQ==

xterm-addon-search@^0.8.2:
version "0.8.2"
resolved "https://registry.yarnpkg.com/xterm-addon-search/-/xterm-addon-search-0.8.2.tgz#be7aa74d5ff12c901707c6ff674229f214318032"
integrity sha512-I1863mjn8P6uVrqm/X+btalVsqjAKLhnhpbP7SavAOpEkI1jJhbHU2UTp7NjeRtcKTks6UWk/ycgds5snDSejg==
xterm-addon-fit@^0.8.0:
version "0.8.0"
resolved "https://registry.yarnpkg.com/xterm-addon-fit/-/xterm-addon-fit-0.8.0.tgz#48ca99015385141918f955ca7819e85f3691d35f"
integrity sha512-yj3Np7XlvxxhYF/EJ7p3KHaMt6OdwQ+HDu573Vx1lRXsVxOcnVJs51RgjZOouIZOczTsskaS+CpXspK81/DLqw==

xterm-addon-search@^0.13.0:
version "0.13.0"
resolved "https://registry.yarnpkg.com/xterm-addon-search/-/xterm-addon-search-0.13.0.tgz#21286f4db48aa949fbefce34bb8bc0c9d3cec627"
integrity sha512-sDUwG4CnqxUjSEFh676DlS3gsh3XYCzAvBPSvJ5OPgF3MRL3iHLPfsb06doRicLC2xXNpeG2cWk8x1qpESWJMA==

xterm@^4.16.0:
version "4.19.0"
resolved "https://registry.yarnpkg.com/xterm/-/xterm-4.19.0.tgz#c0f9d09cd61de1d658f43ca75f992197add9ef6d"
integrity sha512-c3Cp4eOVsYY5Q839dR5IejghRPpxciGmLWWaP9g+ppfMeBChMeLa1DCA+pmX/jyDZ+zxFOmlJL/82qVdayVoGQ==

xterm@^5.3.0:
version "5.3.0"
resolved "https://registry.yarnpkg.com/xterm/-/xterm-5.3.0.tgz#867daf9cc826f3d45b5377320aabd996cb0fce46"
integrity sha512-8QqjlekLUFTrU6x7xck1MsPzPA571K5zNqWm0M0oroYEWVOptZ0+ubQSkQ3uxIEhcIHRujJy6emDWX4A7qyFzg==

y18n@^4.0.0:
version "4.0.3"
resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.3.tgz#b5f259c82cd6e336921efd7bfd8bf560de9eeedf"
Expand Down
Loading