diff --git a/lib/components/term-group.tsx b/lib/components/term-group.tsx index de13b0a8..ae1ec7e3 100644 --- a/lib/components/term-group.tsx +++ b/lib/components/term-group.tsx @@ -106,6 +106,7 @@ class TermGroup_ extends React.PureComponent { macOptionSelectionMode: this.props.macOptionSelectionMode, disableLigatures: this.props.disableLigatures, screenReaderMode: this.props.screenReaderMode, + windowsPty: this.props.windowsPty, uid }); diff --git a/lib/components/term.tsx b/lib/components/term.tsx index a8a0057e..02fcad9f 100644 --- a/lib/components/term.tsx +++ b/lib/components/term.tsx @@ -19,7 +19,7 @@ import 'xterm/css/xterm.css'; const SearchBox = decorate(_SearchBox, 'SearchBox'); -const isWindows = ['Windows', 'Win16', 'Win32', 'WinCE'].includes(navigator.platform); +const isWindows = ['Windows', 'Win16', 'Win32', 'WinCE'].includes(navigator.platform) || process.platform === 'win32'; // map old hterm constants to xterm.js const CURSOR_STYLES = { @@ -59,6 +59,7 @@ const getTermOptions = (props: TermProps): ITerminalOptions => { allowTransparency: needTransparency, macOptionClickForcesSelection: props.macOptionSelectionMode === 'force', windowsMode: isWindows, + ...(isWindows && props.windowsPty && {windowsPty: props.windowsPty}), theme: { foreground: props.foregroundColor, background: backgroundColor, diff --git a/lib/components/terms.tsx b/lib/components/terms.tsx index bc819db3..5695a571 100644 --- a/lib/components/terms.tsx +++ b/lib/components/terms.tsx @@ -119,6 +119,7 @@ export default class Terms extends React.Component { macOptionSelectionMode: this.props.macOptionSelectionMode, disableLigatures: this.props.disableLigatures, screenReaderMode: this.props.screenReaderMode, + windowsPty: this.props.windowsPty, parentProps: this.props }); diff --git a/lib/containers/terms.ts b/lib/containers/terms.ts index c6ca776e..5e934060 100644 --- a/lib/containers/terms.ts +++ b/lib/containers/terms.ts @@ -53,7 +53,8 @@ const mapStateToProps = (state: HyperState) => { webLinksActivationKey: state.ui.webLinksActivationKey, macOptionSelectionMode: state.ui.macOptionSelectionMode, disableLigatures: state.ui.disableLigatures, - screenReaderMode: state.ui.screenReaderMode + screenReaderMode: state.ui.screenReaderMode, + windowsPty: state.ui.windowsPty }; }; diff --git a/lib/hyper.d.ts b/lib/hyper.d.ts index dc49b52a..26937548 100644 --- a/lib/hyper.d.ts +++ b/lib/hyper.d.ts @@ -38,7 +38,7 @@ export type ITermState = Immutable<{ }>; export type cursorShapes = 'BEAM' | 'UNDERLINE' | 'BLOCK'; -import {FontWeight, Terminal} from 'xterm'; +import {FontWeight, IWindowsPty, Terminal} from 'xterm'; import {ColorMap} from './config'; export type uiState = Immutable<{ @@ -103,6 +103,7 @@ export type uiState = Immutable<{ updateVersion: string | null; webGLRenderer: boolean; webLinksActivationKey: 'ctrl' | 'alt' | 'meta' | 'shift' | ''; + windowsPty?: IWindowsPty; }>; export type session = { @@ -308,6 +309,7 @@ export type TermGroupOwnProps = { | 'uiFontFamily' | 'webGLRenderer' | 'webLinksActivationKey' + | 'windowsPty' >; import {TermGroupConnectedProps} from './components/term-group'; @@ -382,6 +384,7 @@ export type TermProps = { url: string | null; webGLRenderer: boolean; webLinksActivationKey: 'ctrl' | 'alt' | 'meta' | 'shift' | ''; + windowsPty?: IWindowsPty; ref_: (uid: string, term: Term | null) => void; } & extensionProps; diff --git a/lib/reducers/ui.ts b/lib/reducers/ui.ts index 4a432d53..313dec00 100644 --- a/lib/reducers/ui.ts +++ b/lib/reducers/ui.ts @@ -22,6 +22,9 @@ import { } from '../constants/sessions'; import {UPDATE_AVAILABLE} from '../constants/updater'; import {uiState, Mutable, IUiReducer} from '../hyper'; +import {release} from 'os'; + +const isWindows = ['Windows', 'Win16', 'Win32', 'WinCE'].includes(navigator.platform) || process.platform === 'win32'; const allowedCursorShapes = new Set(['BEAM', 'BLOCK', 'UNDERLINE']); const allowedCursorBlinkValues = new Set([true, false]); @@ -269,6 +272,15 @@ const reducer: IUiReducer = (state = initial, action) => { ret.screenReaderMode = config.screenReaderMode; } + const buildNumber = parseInt(release().split('.').at(-1) || '0', 10); + if (isWindows && !Number.isNaN(buildNumber) && buildNumber > 0) { + const useConpty = typeof config.useConpty === 'boolean' ? config.useConpty : buildNumber >= 18309; + ret.windowsPty = { + backend: useConpty ? 'conpty' : 'winpty', + buildNumber + }; + } + ret._lastUpdate = now; return ret;