@xterm/xterm 6.1.0-beta.21 → 6.1.0-beta.211

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (158) hide show
  1. package/README.md +61 -38
  2. package/css/xterm.css +29 -22
  3. package/lib/xterm.js +1 -1
  4. package/lib/xterm.js.map +1 -1
  5. package/lib/xterm.mjs +8 -34
  6. package/lib/xterm.mjs.map +4 -4
  7. package/package.json +24 -13
  8. package/src/browser/AccessibilityManager.ts +6 -3
  9. package/src/browser/Clipboard.ts +6 -3
  10. package/src/browser/CoreBrowserTerminal.ts +147 -318
  11. package/src/browser/Dom.ts +178 -0
  12. package/src/browser/Linkifier.ts +11 -11
  13. package/src/browser/OscLinkProvider.ts +3 -1
  14. package/src/browser/RenderDebouncer.ts +2 -2
  15. package/src/browser/TimeBasedDebouncer.ts +2 -2
  16. package/src/browser/Types.ts +12 -11
  17. package/src/browser/Viewport.ts +55 -20
  18. package/src/browser/decorations/BufferDecorationRenderer.ts +1 -1
  19. package/src/browser/decorations/OverviewRulerRenderer.ts +33 -17
  20. package/src/browser/input/CompositionHelper.ts +44 -8
  21. package/src/browser/public/Terminal.ts +25 -28
  22. package/src/browser/renderer/dom/DomRenderer.ts +205 -41
  23. package/src/browser/renderer/dom/DomRendererRowFactory.ts +19 -13
  24. package/src/browser/renderer/dom/WidthCache.ts +54 -52
  25. package/src/browser/renderer/shared/Constants.ts +7 -0
  26. package/src/browser/renderer/shared/TextBlinkStateManager.ts +97 -0
  27. package/src/browser/renderer/shared/Types.ts +8 -2
  28. package/src/browser/scrollable/abstractScrollbar.ts +300 -0
  29. package/src/browser/scrollable/fastDomNode.ts +126 -0
  30. package/src/browser/scrollable/globalPointerMoveMonitor.ts +90 -0
  31. package/src/browser/scrollable/horizontalScrollbar.ts +85 -0
  32. package/src/browser/scrollable/mouseEvent.ts +292 -0
  33. package/src/browser/scrollable/scrollable.ts +486 -0
  34. package/src/browser/scrollable/scrollableElement.ts +579 -0
  35. package/src/browser/scrollable/scrollableElementOptions.ts +161 -0
  36. package/src/browser/scrollable/scrollbarArrow.ts +110 -0
  37. package/src/browser/scrollable/scrollbarState.ts +246 -0
  38. package/src/browser/scrollable/scrollbarVisibilityController.ts +113 -0
  39. package/src/browser/scrollable/touch.ts +485 -0
  40. package/src/browser/scrollable/verticalScrollbar.ts +143 -0
  41. package/src/browser/scrollable/widget.ts +23 -0
  42. package/src/browser/services/CharSizeService.ts +2 -2
  43. package/src/browser/services/CoreBrowserService.ts +7 -5
  44. package/src/browser/services/KeyboardService.ts +67 -0
  45. package/src/browser/services/LinkProviderService.ts +1 -1
  46. package/src/browser/services/MouseCoordsService.ts +47 -0
  47. package/src/browser/services/MouseService.ts +518 -25
  48. package/src/browser/services/RenderService.ts +22 -15
  49. package/src/browser/services/SelectionService.ts +16 -8
  50. package/src/browser/services/Services.ts +40 -17
  51. package/src/browser/services/ThemeService.ts +2 -2
  52. package/src/common/Async.ts +105 -0
  53. package/src/common/CircularList.ts +2 -2
  54. package/src/common/Color.ts +8 -0
  55. package/src/common/CoreTerminal.ts +28 -18
  56. package/src/common/Event.ts +118 -0
  57. package/src/common/InputHandler.ts +263 -43
  58. package/src/common/Lifecycle.ts +113 -0
  59. package/src/common/Platform.ts +13 -3
  60. package/src/common/SortedList.ts +7 -3
  61. package/src/common/TaskQueue.ts +14 -5
  62. package/src/common/Types.ts +35 -15
  63. package/src/common/Version.ts +9 -0
  64. package/src/common/buffer/Buffer.ts +20 -14
  65. package/src/common/buffer/BufferLine.ts +4 -5
  66. package/src/common/buffer/BufferSet.ts +7 -6
  67. package/src/common/buffer/CellData.ts +57 -0
  68. package/src/common/buffer/Marker.ts +2 -2
  69. package/src/common/buffer/Types.ts +6 -2
  70. package/src/common/data/EscapeSequences.ts +71 -70
  71. package/src/common/input/Keyboard.ts +14 -7
  72. package/src/common/input/KittyKeyboard.ts +519 -0
  73. package/src/common/input/Win32InputMode.ts +297 -0
  74. package/src/common/input/WriteBuffer.ts +34 -2
  75. package/src/common/input/XParseColor.ts +2 -2
  76. package/src/common/parser/ApcParser.ts +245 -0
  77. package/src/common/parser/Constants.ts +22 -4
  78. package/src/common/parser/DcsParser.ts +5 -5
  79. package/src/common/parser/EscapeSequenceParser.ts +167 -57
  80. package/src/common/parser/OscParser.ts +5 -5
  81. package/src/common/parser/Params.ts +13 -0
  82. package/src/common/parser/Types.ts +36 -2
  83. package/src/common/public/BufferLineApiView.ts +2 -2
  84. package/src/common/public/BufferNamespaceApi.ts +2 -2
  85. package/src/common/public/ParserApi.ts +3 -0
  86. package/src/common/services/BufferService.ts +8 -5
  87. package/src/common/services/CharsetService.ts +4 -0
  88. package/src/common/services/CoreService.ts +18 -4
  89. package/src/common/services/DecorationService.ts +24 -8
  90. package/src/common/services/LogService.ts +1 -31
  91. package/src/common/services/{CoreMouseService.ts → MouseStateService.ts} +21 -132
  92. package/src/common/services/OptionsService.ts +13 -4
  93. package/src/common/services/Services.ts +47 -40
  94. package/src/common/services/UnicodeService.ts +1 -1
  95. package/typings/xterm.d.ts +316 -32
  96. package/src/common/TypedArrayUtils.ts +0 -17
  97. package/src/vs/base/browser/browser.ts +0 -141
  98. package/src/vs/base/browser/canIUse.ts +0 -49
  99. package/src/vs/base/browser/dom.ts +0 -2369
  100. package/src/vs/base/browser/fastDomNode.ts +0 -316
  101. package/src/vs/base/browser/globalPointerMoveMonitor.ts +0 -112
  102. package/src/vs/base/browser/iframe.ts +0 -135
  103. package/src/vs/base/browser/keyboardEvent.ts +0 -213
  104. package/src/vs/base/browser/mouseEvent.ts +0 -229
  105. package/src/vs/base/browser/touch.ts +0 -372
  106. package/src/vs/base/browser/ui/scrollbar/abstractScrollbar.ts +0 -303
  107. package/src/vs/base/browser/ui/scrollbar/horizontalScrollbar.ts +0 -114
  108. package/src/vs/base/browser/ui/scrollbar/scrollableElement.ts +0 -720
  109. package/src/vs/base/browser/ui/scrollbar/scrollableElementOptions.ts +0 -165
  110. package/src/vs/base/browser/ui/scrollbar/scrollbarArrow.ts +0 -114
  111. package/src/vs/base/browser/ui/scrollbar/scrollbarState.ts +0 -243
  112. package/src/vs/base/browser/ui/scrollbar/scrollbarVisibilityController.ts +0 -118
  113. package/src/vs/base/browser/ui/scrollbar/verticalScrollbar.ts +0 -116
  114. package/src/vs/base/browser/ui/widget.ts +0 -57
  115. package/src/vs/base/browser/window.ts +0 -14
  116. package/src/vs/base/common/arrays.ts +0 -887
  117. package/src/vs/base/common/arraysFind.ts +0 -202
  118. package/src/vs/base/common/assert.ts +0 -71
  119. package/src/vs/base/common/async.ts +0 -1992
  120. package/src/vs/base/common/cancellation.ts +0 -148
  121. package/src/vs/base/common/charCode.ts +0 -450
  122. package/src/vs/base/common/collections.ts +0 -140
  123. package/src/vs/base/common/decorators.ts +0 -130
  124. package/src/vs/base/common/equals.ts +0 -146
  125. package/src/vs/base/common/errors.ts +0 -303
  126. package/src/vs/base/common/event.ts +0 -1778
  127. package/src/vs/base/common/functional.ts +0 -32
  128. package/src/vs/base/common/hash.ts +0 -316
  129. package/src/vs/base/common/iterator.ts +0 -159
  130. package/src/vs/base/common/keyCodes.ts +0 -526
  131. package/src/vs/base/common/keybindings.ts +0 -284
  132. package/src/vs/base/common/lazy.ts +0 -47
  133. package/src/vs/base/common/lifecycle.ts +0 -801
  134. package/src/vs/base/common/linkedList.ts +0 -142
  135. package/src/vs/base/common/map.ts +0 -202
  136. package/src/vs/base/common/numbers.ts +0 -98
  137. package/src/vs/base/common/observable.ts +0 -76
  138. package/src/vs/base/common/observableInternal/api.ts +0 -31
  139. package/src/vs/base/common/observableInternal/autorun.ts +0 -281
  140. package/src/vs/base/common/observableInternal/base.ts +0 -489
  141. package/src/vs/base/common/observableInternal/debugName.ts +0 -145
  142. package/src/vs/base/common/observableInternal/derived.ts +0 -428
  143. package/src/vs/base/common/observableInternal/lazyObservableValue.ts +0 -146
  144. package/src/vs/base/common/observableInternal/logging.ts +0 -328
  145. package/src/vs/base/common/observableInternal/promise.ts +0 -209
  146. package/src/vs/base/common/observableInternal/utils.ts +0 -610
  147. package/src/vs/base/common/platform.ts +0 -281
  148. package/src/vs/base/common/scrollable.ts +0 -522
  149. package/src/vs/base/common/sequence.ts +0 -34
  150. package/src/vs/base/common/stopwatch.ts +0 -43
  151. package/src/vs/base/common/strings.ts +0 -557
  152. package/src/vs/base/common/symbols.ts +0 -9
  153. package/src/vs/base/common/uint.ts +0 -59
  154. package/src/vs/patches/nls.ts +0 -90
  155. package/src/vs/typings/base-common.d.ts +0 -20
  156. package/src/vs/typings/require.d.ts +0 -42
  157. package/src/vs/typings/vscode-globals-nls.d.ts +0 -36
  158. package/src/vs/typings/vscode-globals-product.d.ts +0 -33
@@ -8,20 +8,22 @@ import { IInputHandler, IAttributeData, IDisposable, IWindowOptions, IColorEvent
8
8
  import { C0, C1 } from 'common/data/EscapeSequences';
9
9
  import { CHARSETS, DEFAULT_CHARSET } from 'common/data/Charsets';
10
10
  import { EscapeSequenceParser } from 'common/parser/EscapeSequenceParser';
11
- import { Disposable } from 'vs/base/common/lifecycle';
11
+ import { Disposable } from 'common/Lifecycle';
12
12
  import { StringToUtf32, stringFromCodePoint, Utf8ToUtf32 } from 'common/input/TextDecoder';
13
13
  import { BufferLine, DEFAULT_ATTR_DATA } from 'common/buffer/BufferLine';
14
14
  import { IParsingState, IEscapeSequenceParser, IParams, IFunctionIdentifier } from 'common/parser/Types';
15
15
  import { NULL_CELL_CODE, NULL_CELL_WIDTH, Attributes, FgFlags, BgFlags, Content, UnderlineStyle } from 'common/buffer/Constants';
16
16
  import { CellData } from 'common/buffer/CellData';
17
17
  import { AttributeData } from 'common/buffer/AttributeData';
18
- import { ICoreService, IBufferService, IOptionsService, ILogService, ICoreMouseService, ICharsetService, IUnicodeService, LogLevelEnum, IOscLinkService } from 'common/services/Services';
18
+ import { ICoreService, IBufferService, IOptionsService, ILogService, IMouseStateService, ICharsetService, IUnicodeService, LogLevelEnum, IOscLinkService } from 'common/services/Services';
19
19
  import { UnicodeService } from 'common/services/UnicodeService';
20
20
  import { OscHandler } from 'common/parser/OscParser';
21
21
  import { DcsHandler } from 'common/parser/DcsParser';
22
+ import { ApcHandler } from 'common/parser/ApcParser';
22
23
  import { IBuffer } from 'common/buffer/Types';
23
24
  import { parseColor } from 'common/input/XParseColor';
24
- import { Emitter } from 'vs/base/common/event';
25
+ import { Emitter } from 'common/Event';
26
+ import { XTERM_VERSION } from 'common/Version';
25
27
 
26
28
  /**
27
29
  * Map collect to glevel. Used in `selectCharset`.
@@ -158,6 +160,8 @@ export class InputHandler extends Disposable implements IInputHandler {
158
160
  public readonly onTitleChange = this._onTitleChange.event;
159
161
  private readonly _onColor = this._register(new Emitter<IColorEvent>());
160
162
  public readonly onColor = this._onColor.event;
163
+ private readonly _onRequestColorSchemeQuery = this._register(new Emitter<void>());
164
+ public readonly onRequestColorSchemeQuery = this._onRequestColorSchemeQuery.event;
161
165
 
162
166
  private _parseStack: IParseStack = {
163
167
  paused: false,
@@ -174,7 +178,7 @@ export class InputHandler extends Disposable implements IInputHandler {
174
178
  private readonly _logService: ILogService,
175
179
  private readonly _optionsService: IOptionsService,
176
180
  private readonly _oscLinkService: IOscLinkService,
177
- private readonly _coreMouseService: ICoreMouseService,
181
+ private readonly _mouseStateService: IMouseStateService,
178
182
  private readonly _unicodeService: IUnicodeService,
179
183
  private readonly _parser: IEscapeSequenceParser = new EscapeSequenceParser()
180
184
  ) {
@@ -239,6 +243,7 @@ export class InputHandler extends Disposable implements IInputHandler {
239
243
  this._parser.registerCsiHandler({ final: 'T' }, params => this.scrollDown(params));
240
244
  this._parser.registerCsiHandler({ final: 'X' }, params => this.eraseChars(params));
241
245
  this._parser.registerCsiHandler({ final: 'Z' }, params => this.cursorBackwardTab(params));
246
+ this._parser.registerCsiHandler({ final: '^' }, params => this.scrollDown(params));
242
247
  this._parser.registerCsiHandler({ final: '`' }, params => this.charPosAbsolute(params));
243
248
  this._parser.registerCsiHandler({ final: 'a' }, params => this.hPositionRelative(params));
244
249
  this._parser.registerCsiHandler({ final: 'b' }, params => this.repeatPrecedingCharacter(params));
@@ -256,6 +261,7 @@ export class InputHandler extends Disposable implements IInputHandler {
256
261
  this._parser.registerCsiHandler({ final: 'n' }, params => this.deviceStatus(params));
257
262
  this._parser.registerCsiHandler({ prefix: '?', final: 'n' }, params => this.deviceStatusPrivate(params));
258
263
  this._parser.registerCsiHandler({ intermediates: '!', final: 'p' }, params => this.softReset(params));
264
+ this._parser.registerCsiHandler({ prefix: '>', final: 'q' }, params => this.sendXtVersion(params));
259
265
  this._parser.registerCsiHandler({ intermediates: ' ', final: 'q' }, params => this.setCursorStyle(params));
260
266
  this._parser.registerCsiHandler({ final: 'r' }, params => this.setScrollRegion(params));
261
267
  this._parser.registerCsiHandler({ final: 's' }, params => this.saveCursor(params));
@@ -267,6 +273,12 @@ export class InputHandler extends Disposable implements IInputHandler {
267
273
  this._parser.registerCsiHandler({ intermediates: '$', final: 'p' }, params => this.requestMode(params, true));
268
274
  this._parser.registerCsiHandler({ prefix: '?', intermediates: '$', final: 'p' }, params => this.requestMode(params, false));
269
275
 
276
+ // Kitty keyboard protocol handlers
277
+ this._parser.registerCsiHandler({ prefix: '=', final: 'u' }, params => this.kittyKeyboardSet(params));
278
+ this._parser.registerCsiHandler({ prefix: '?', final: 'u' }, params => this.kittyKeyboardQuery(params));
279
+ this._parser.registerCsiHandler({ prefix: '>', final: 'u' }, params => this.kittyKeyboardPush(params));
280
+ this._parser.registerCsiHandler({ prefix: '<', final: 'u' }, params => this.kittyKeyboardPop(params));
281
+
270
282
  /**
271
283
  * execute handler
272
284
  */
@@ -395,8 +407,19 @@ export class InputHandler extends Disposable implements IInputHandler {
395
407
  private _logSlowResolvingAsync(p: Promise<boolean>): void {
396
408
  // log a limited warning about an async handler taking too long
397
409
  if (this._logService.logLevel <= LogLevelEnum.WARN) {
398
- Promise.race([p, new Promise((res, rej) => setTimeout(() => rej('#SLOW_TIMEOUT'), SLOW_ASYNC_LIMIT))])
399
- .catch(err => {
410
+ let slowTimeout: ReturnType<typeof setTimeout> | undefined;
411
+ const slowPromise = new Promise<never>((_res, rej) => {
412
+ slowTimeout = setTimeout(() => rej('#SLOW_TIMEOUT'), SLOW_ASYNC_LIMIT);
413
+ });
414
+ Promise.race([p, slowPromise])
415
+ .then(() => {
416
+ if (slowTimeout !== undefined) {
417
+ clearTimeout(slowTimeout);
418
+ }
419
+ }, err => {
420
+ if (slowTimeout !== undefined) {
421
+ clearTimeout(slowTimeout);
422
+ }
400
423
  if (err !== '#SLOW_TIMEOUT') {
401
424
  throw err;
402
425
  }
@@ -518,7 +541,13 @@ export class InputHandler extends Disposable implements IInputHandler {
518
541
  const wraparoundMode = this._coreService.decPrivateModes.wraparound;
519
542
  const insertMode = this._coreService.modes.insertMode;
520
543
  const curAttr = this._curAttrData;
521
- let bufferRow = this._activeBuffer.lines.get(this._activeBuffer.ybase + this._activeBuffer.y)!;
544
+ let bufferRow = this._activeBuffer.lines.get(this._activeBuffer.ybase + this._activeBuffer.y);
545
+
546
+ // Defensive check: bufferRow can be undefined if a resize occurred mid-write due to async
547
+ // scheduling gaps in WriteBuffer. See https://github.com/xtermjs/xterm.js/issues/5597
548
+ if (!bufferRow) {
549
+ return;
550
+ }
522
551
 
523
552
  this._dirtyRowTracker.markDirty(this._activeBuffer.y);
524
553
 
@@ -531,6 +560,12 @@ export class InputHandler extends Disposable implements IInputHandler {
531
560
  for (let pos = start; pos < end; ++pos) {
532
561
  code = data[pos];
533
562
 
563
+ // Soft hyphen's (U+00AD) behavior is ambiguous and differs across terminals. We opt to treat
564
+ // it as a zero-width hint to text layout engines and simply ignore it.
565
+ if (code === 0xAD) {
566
+ continue;
567
+ }
568
+
534
569
  // get charset replacement character
535
570
  // charset is only defined for ASCII, therefore we only
536
571
  // search for an replacement char if code < 127
@@ -577,7 +612,10 @@ export class InputHandler extends Disposable implements IInputHandler {
577
612
  this._activeBuffer.lines.get(this._activeBuffer.ybase + this._activeBuffer.y)!.isWrapped = true;
578
613
  }
579
614
  // row changed, get it again
580
- bufferRow = this._activeBuffer.lines.get(this._activeBuffer.ybase + this._activeBuffer.y)!;
615
+ bufferRow = this._activeBuffer.lines.get(this._activeBuffer.ybase + this._activeBuffer.y);
616
+ if (!bufferRow) {
617
+ return;
618
+ }
581
619
  if (oldWidth > 0 && bufferRow instanceof BufferLine) {
582
620
  // Combining character widens 1 column to 2.
583
621
  // Move old character to next line.
@@ -688,6 +726,13 @@ export class InputHandler extends Disposable implements IInputHandler {
688
726
  return this._parser.registerOscHandler(ident, new OscHandler(callback));
689
727
  }
690
728
 
729
+ /**
730
+ * Forward registerApcHandler from parser.
731
+ */
732
+ public registerApcHandler(ident: number, callback: (data: string) => boolean | Promise<boolean>): IDisposable {
733
+ return this._parser.registerApcHandler(ident, new ApcHandler(callback));
734
+ }
735
+
691
736
  /**
692
737
  * BEL
693
738
  * Bell (Ctrl-G).
@@ -1145,7 +1190,10 @@ export class InputHandler extends Disposable implements IInputHandler {
1145
1190
  * @param respectProtect Whether to respect the protection attribute (DECSCA).
1146
1191
  */
1147
1192
  private _eraseInBufferLine(y: number, start: number, end: number, clearWrap: boolean = false, respectProtect: boolean = false): void {
1148
- const line = this._activeBuffer.lines.get(this._activeBuffer.ybase + y)!;
1193
+ const line = this._activeBuffer.lines.get(this._activeBuffer.ybase + y);
1194
+ if (!line) {
1195
+ return;
1196
+ }
1149
1197
  line.replaceCells(
1150
1198
  start,
1151
1199
  end,
@@ -1215,7 +1263,10 @@ export class InputHandler extends Disposable implements IInputHandler {
1215
1263
  this._eraseInBufferLine(j, 0, this._activeBuffer.x + 1, true, respectProtect);
1216
1264
  if (this._activeBuffer.x + 1 >= this._bufferService.cols) {
1217
1265
  // Deleted entire previous line. This next line can no longer be wrapped.
1218
- this._activeBuffer.lines.get(j + 1)!.isWrapped = false;
1266
+ const nextLine = this._activeBuffer.lines.get(j + 1);
1267
+ if (nextLine) {
1268
+ nextLine.isWrapped = false;
1269
+ }
1219
1270
  }
1220
1271
  while (j--) {
1221
1272
  this._resetBufferLine(j, respectProtect);
@@ -1721,12 +1772,28 @@ export class InputHandler extends Disposable implements IInputHandler {
1721
1772
  return true;
1722
1773
  }
1723
1774
 
1775
+ /**
1776
+ * CSI > Ps q
1777
+ * Ps = 0 => Report xterm name and version (XTVERSION).
1778
+ *
1779
+ * The response is a DCS sequence identifying the version: DCS > | text ST
1780
+ *
1781
+ * @vt: #Y CSI XTVERSION "Report Xterm Version" "CSI > q" "Report the terminal name and version."
1782
+ */
1783
+ public sendXtVersion(params: IParams): boolean {
1784
+ if (params.params[0] > 0) {
1785
+ return true;
1786
+ }
1787
+ this._coreService.triggerDataEvent(`${C0.ESC}P>|xterm.js(${XTERM_VERSION})${C0.ESC}\\`);
1788
+ return true;
1789
+ }
1790
+
1724
1791
  /**
1725
1792
  * Evaluate if the current terminal is the given argument.
1726
1793
  * @param term The terminal name to evaluate
1727
1794
  */
1728
1795
  private _is(term: string): boolean {
1729
- return (this._optionsService.rawOptions.termName + '').indexOf(term) === 0;
1796
+ return (this._optionsService.rawOptions.termName + '').startsWith(term);
1730
1797
  }
1731
1798
 
1732
1799
  /**
@@ -1853,7 +1920,7 @@ export class InputHandler extends Disposable implements IInputHandler {
1853
1920
  * | 7 | Auto-wrap Mode (DECAWM). | #Y |
1854
1921
  * | 8 | Auto-repeat Keys (DECARM). Always on. | #N |
1855
1922
  * | 9 | X10 xterm mouse protocol. | #Y |
1856
- * | 12 | Start Blinking Cursor. | #Y |
1923
+ * | 12 | Start Blinking Cursor. | #P[Requires the allowSetCursorBlink quirk option enabled.] |
1857
1924
  * | 25 | Show Cursor (DECTCEM). | #Y |
1858
1925
  * | 45 | Reverse wrap-around. | #Y |
1859
1926
  * | 47 | Use Alternate Screen Buffer. | #Y |
@@ -1906,7 +1973,9 @@ export class InputHandler extends Disposable implements IInputHandler {
1906
1973
  this._coreService.decPrivateModes.wraparound = true;
1907
1974
  break;
1908
1975
  case 12:
1909
- this._optionsService.options.cursorBlink = true;
1976
+ if (this._optionsService.rawOptions.quirks?.allowSetCursorBlink) {
1977
+ this._optionsService.options.cursorBlink = true;
1978
+ }
1910
1979
  break;
1911
1980
  case 45:
1912
1981
  this._coreService.decPrivateModes.reverseWraparound = true;
@@ -1918,19 +1987,19 @@ export class InputHandler extends Disposable implements IInputHandler {
1918
1987
  break;
1919
1988
  case 9: // X10 Mouse
1920
1989
  // no release, no motion, no wheel, no modifiers.
1921
- this._coreMouseService.activeProtocol = 'X10';
1990
+ this._mouseStateService.activeProtocol = 'X10';
1922
1991
  break;
1923
1992
  case 1000: // vt200 mouse
1924
1993
  // no motion.
1925
- this._coreMouseService.activeProtocol = 'VT200';
1994
+ this._mouseStateService.activeProtocol = 'VT200';
1926
1995
  break;
1927
1996
  case 1002: // button event mouse
1928
- this._coreMouseService.activeProtocol = 'DRAG';
1997
+ this._mouseStateService.activeProtocol = 'DRAG';
1929
1998
  break;
1930
1999
  case 1003: // any event mouse
1931
2000
  // any event - sends motion events,
1932
2001
  // even if there is no button held down.
1933
- this._coreMouseService.activeProtocol = 'ANY';
2002
+ this._mouseStateService.activeProtocol = 'ANY';
1934
2003
  break;
1935
2004
  case 1004: // send focusin/focusout events
1936
2005
  // focusin: ^[[I
@@ -1942,13 +2011,13 @@ export class InputHandler extends Disposable implements IInputHandler {
1942
2011
  this._logService.debug('DECSET 1005 not supported (see #2507)');
1943
2012
  break;
1944
2013
  case 1006: // sgr ext mode mouse
1945
- this._coreMouseService.activeEncoding = 'SGR';
2014
+ this._mouseStateService.activeEncoding = 'SGR';
1946
2015
  break;
1947
2016
  case 1015: // urxvt ext mode mouse - removed in #2507
1948
2017
  this._logService.debug('DECSET 1015 not supported (see #2507)');
1949
2018
  break;
1950
2019
  case 1016: // sgr pixels mode mouse
1951
- this._coreMouseService.activeEncoding = 'SGR_PIXELS';
2020
+ this._mouseStateService.activeEncoding = 'SGR_PIXELS';
1952
2021
  break;
1953
2022
  case 25: // show cursor
1954
2023
  this._coreService.isCursorHidden = false;
@@ -1961,6 +2030,12 @@ export class InputHandler extends Disposable implements IInputHandler {
1961
2030
  // FALL-THROUGH
1962
2031
  case 47: // alt screen buffer
1963
2032
  case 1047: // alt screen buffer
2033
+ // Swap kitty keyboard flags: save main, restore alt
2034
+ if (this._optionsService.rawOptions.vtExtensions?.kittyKeyboard) {
2035
+ const state = this._coreService.kittyKeyboard;
2036
+ state.mainFlags = state.flags;
2037
+ state.flags = state.altFlags;
2038
+ }
1964
2039
  this._bufferService.buffers.activateAltBuffer(this._eraseAttrData());
1965
2040
  this._coreService.isCursorInitialized = true;
1966
2041
  this._onRequestRefreshRows.fire(undefined);
@@ -1972,6 +2047,16 @@ export class InputHandler extends Disposable implements IInputHandler {
1972
2047
  case 2026: // synchronized output (https://github.com/contour-terminal/vt-extensions/blob/master/synchronized-output.md)
1973
2048
  this._coreService.decPrivateModes.synchronizedOutput = true;
1974
2049
  break;
2050
+ case 2031: // color scheme updates (https://contour-terminal.org/vt-extensions/color-palette-update-notifications/)
2051
+ if (this._optionsService.rawOptions.vtExtensions?.colorSchemeQuery ?? true) {
2052
+ this._coreService.decPrivateModes.colorSchemeUpdates = true;
2053
+ }
2054
+ break;
2055
+ case 9001: // win32-input-mode (https://github.com/microsoft/terminal/blob/main/doc/specs/%234999%20-%20Improved%20keyboard%20handling%20in%20Conpty.md)
2056
+ if (this._optionsService.rawOptions.vtExtensions?.win32InputMode) {
2057
+ this._coreService.decPrivateModes.win32InputMode = true;
2058
+ }
2059
+ break;
1975
2060
  }
1976
2061
  }
1977
2062
  return true;
@@ -2101,7 +2186,7 @@ export class InputHandler extends Disposable implements IInputHandler {
2101
2186
  * | 7 | No Wraparound Mode (DECAWM). | #Y |
2102
2187
  * | 8 | No Auto-repeat Keys (DECARM). | #N |
2103
2188
  * | 9 | Don't send Mouse X & Y on button press. | #Y |
2104
- * | 12 | Stop Blinking Cursor. | #Y |
2189
+ * | 12 | Stop Blinking Cursor. | #P[Requires the allowSetCursorBlink quirk option enabled.] |
2105
2190
  * | 25 | Hide Cursor (DECTCEM). | #Y |
2106
2191
  * | 45 | No reverse wrap-around. | #Y |
2107
2192
  * | 47 | Use Normal Screen Buffer. | #Y |
@@ -2147,7 +2232,9 @@ export class InputHandler extends Disposable implements IInputHandler {
2147
2232
  this._coreService.decPrivateModes.wraparound = false;
2148
2233
  break;
2149
2234
  case 12:
2150
- this._optionsService.options.cursorBlink = false;
2235
+ if (this._optionsService.rawOptions.quirks?.allowSetCursorBlink) {
2236
+ this._optionsService.options.cursorBlink = false;
2237
+ }
2151
2238
  break;
2152
2239
  case 45:
2153
2240
  this._coreService.decPrivateModes.reverseWraparound = false;
@@ -2161,7 +2248,7 @@ export class InputHandler extends Disposable implements IInputHandler {
2161
2248
  case 1000: // vt200 mouse
2162
2249
  case 1002: // button event mouse
2163
2250
  case 1003: // any event mouse
2164
- this._coreMouseService.activeProtocol = 'NONE';
2251
+ this._mouseStateService.activeProtocol = 'NONE';
2165
2252
  break;
2166
2253
  case 1004: // send focusin/focusout events
2167
2254
  this._coreService.decPrivateModes.sendFocus = false;
@@ -2170,13 +2257,13 @@ export class InputHandler extends Disposable implements IInputHandler {
2170
2257
  this._logService.debug('DECRST 1005 not supported (see #2507)');
2171
2258
  break;
2172
2259
  case 1006: // sgr ext mode mouse
2173
- this._coreMouseService.activeEncoding = 'DEFAULT';
2260
+ this._mouseStateService.activeEncoding = 'DEFAULT';
2174
2261
  break;
2175
2262
  case 1015: // urxvt ext mode mouse - removed in #2507
2176
2263
  this._logService.debug('DECRST 1015 not supported (see #2507)');
2177
2264
  break;
2178
2265
  case 1016: // sgr pixels mode mouse
2179
- this._coreMouseService.activeEncoding = 'DEFAULT';
2266
+ this._mouseStateService.activeEncoding = 'DEFAULT';
2180
2267
  break;
2181
2268
  case 25: // hide cursor
2182
2269
  this._coreService.isCursorHidden = true;
@@ -2188,6 +2275,12 @@ export class InputHandler extends Disposable implements IInputHandler {
2188
2275
  // FALL-THROUGH
2189
2276
  case 47: // normal screen buffer
2190
2277
  case 1047: // normal screen buffer - clearing it first
2278
+ // Swap kitty keyboard flags: save alt, restore main
2279
+ if (this._optionsService.rawOptions.vtExtensions?.kittyKeyboard) {
2280
+ const state = this._coreService.kittyKeyboard;
2281
+ state.altFlags = state.flags;
2282
+ state.flags = state.mainFlags;
2283
+ }
2191
2284
  // Ensure the selection manager has the correct buffer
2192
2285
  this._bufferService.buffers.activateNormalBuffer();
2193
2286
  if (params.params[i] === 1049) {
@@ -2204,6 +2297,16 @@ export class InputHandler extends Disposable implements IInputHandler {
2204
2297
  this._coreService.decPrivateModes.synchronizedOutput = false;
2205
2298
  this._onRequestRefreshRows.fire(undefined);
2206
2299
  break;
2300
+ case 2031: // color scheme updates (https://contour-terminal.org/vt-extensions/color-palette-update-notifications/)
2301
+ if (this._optionsService.rawOptions.vtExtensions?.colorSchemeQuery ?? true) {
2302
+ this._coreService.decPrivateModes.colorSchemeUpdates = false;
2303
+ }
2304
+ break;
2305
+ case 9001: // win32-input-mode
2306
+ if (this._optionsService.rawOptions.vtExtensions?.win32InputMode) {
2307
+ this._coreService.decPrivateModes.win32InputMode = false;
2308
+ }
2309
+ break;
2207
2310
  }
2208
2311
  }
2209
2312
  return true;
@@ -2254,7 +2357,7 @@ export class InputHandler extends Disposable implements IInputHandler {
2254
2357
 
2255
2358
  // access helpers
2256
2359
  const dm = this._coreService.decPrivateModes;
2257
- const { activeProtocol: mouseProtocol, activeEncoding: mouseEncoding } = this._coreMouseService;
2360
+ const { activeProtocol: mouseProtocol, activeEncoding: mouseEncoding } = this._mouseStateService;
2258
2361
  const cs = this._coreService;
2259
2362
  const { buffers, cols } = this._bufferService;
2260
2363
  const { active, alt } = buffers;
@@ -2299,6 +2402,7 @@ export class InputHandler extends Disposable implements IInputHandler {
2299
2402
  if (p === 47 || p === 1047 || p === 1049) return f(p, b2v(active === alt));
2300
2403
  if (p === 2004) return f(p, b2v(dm.bracketedPasteMode));
2301
2404
  if (p === 2026) return f(p, b2v(dm.synchronizedOutput));
2405
+ if (p === 9001) return this._optionsService.rawOptions.vtExtensions?.win32InputMode ? f(p, b2v(dm.win32InputMode)) : f(p, V.NOT_RECOGNIZED);
2302
2406
  return f(p, V.NOT_RECOGNIZED);
2303
2407
  }
2304
2408
 
@@ -2311,7 +2415,7 @@ export class InputHandler extends Disposable implements IInputHandler {
2311
2415
  color &= ~Attributes.RGB_MASK;
2312
2416
  color |= AttributeData.fromColorRGB([c1, c2, c3]);
2313
2417
  } else if (mode === 5) {
2314
- color &= ~(Attributes.CM_MASK | Attributes.PCOLOR_MASK);
2418
+ color &= ~(Attributes.CM_MASK | Attributes.RGB_MASK);
2315
2419
  color |= Attributes.CM_P256 | (c1 & 0xff);
2316
2420
  }
2317
2421
  return color;
@@ -2476,6 +2580,8 @@ export class InputHandler extends Disposable implements IInputHandler {
2476
2580
  * | 53 | Overlined. | #Y |
2477
2581
  * | 55 | Not Overlined. | #Y |
2478
2582
  * | 58 | Underline color: Extended color. | #P[Support for RGB and indexed colors, see below.] |
2583
+ * | 221 | Not bold (kitty extension). | #Y |
2584
+ * | 222 | Not faint (kitty extension). | #Y |
2479
2585
  * | 90 - 97 | Bright foreground color (analogous to 30 - 37). | #Y |
2480
2586
  * | 100 - 107 | Bright background color (analogous to 40 - 47). | #Y |
2481
2587
  *
@@ -2522,19 +2628,19 @@ export class InputHandler extends Disposable implements IInputHandler {
2522
2628
  p = params.params[i];
2523
2629
  if (p >= 30 && p <= 37) {
2524
2630
  // fg color 8
2525
- attr.fg &= ~(Attributes.CM_MASK | Attributes.PCOLOR_MASK);
2631
+ attr.fg &= ~(Attributes.CM_MASK | Attributes.RGB_MASK);
2526
2632
  attr.fg |= Attributes.CM_P16 | (p - 30);
2527
2633
  } else if (p >= 40 && p <= 47) {
2528
2634
  // bg color 8
2529
- attr.bg &= ~(Attributes.CM_MASK | Attributes.PCOLOR_MASK);
2635
+ attr.bg &= ~(Attributes.CM_MASK | Attributes.RGB_MASK);
2530
2636
  attr.bg |= Attributes.CM_P16 | (p - 40);
2531
2637
  } else if (p >= 90 && p <= 97) {
2532
2638
  // fg color 16
2533
- attr.fg &= ~(Attributes.CM_MASK | Attributes.PCOLOR_MASK);
2639
+ attr.fg &= ~(Attributes.CM_MASK | Attributes.RGB_MASK);
2534
2640
  attr.fg |= Attributes.CM_P16 | (p - 90) | 8;
2535
2641
  } else if (p >= 100 && p <= 107) {
2536
2642
  // bg color 16
2537
- attr.bg &= ~(Attributes.CM_MASK | Attributes.PCOLOR_MASK);
2643
+ attr.bg &= ~(Attributes.CM_MASK | Attributes.RGB_MASK);
2538
2644
  attr.bg |= Attributes.CM_P16 | (p - 100) | 8;
2539
2645
  } else if (p === 0) {
2540
2646
  // default
@@ -2594,11 +2700,11 @@ export class InputHandler extends Disposable implements IInputHandler {
2594
2700
  } else if (p === 39) {
2595
2701
  // reset fg
2596
2702
  attr.fg &= ~(Attributes.CM_MASK | Attributes.RGB_MASK);
2597
- attr.fg |= DEFAULT_ATTR_DATA.fg & (Attributes.PCOLOR_MASK | Attributes.RGB_MASK);
2703
+ attr.fg |= DEFAULT_ATTR_DATA.fg & Attributes.RGB_MASK;
2598
2704
  } else if (p === 49) {
2599
2705
  // reset bg
2600
2706
  attr.bg &= ~(Attributes.CM_MASK | Attributes.RGB_MASK);
2601
- attr.bg |= DEFAULT_ATTR_DATA.bg & (Attributes.PCOLOR_MASK | Attributes.RGB_MASK);
2707
+ attr.bg |= DEFAULT_ATTR_DATA.bg & Attributes.RGB_MASK;
2602
2708
  } else if (p === 38 || p === 48 || p === 58) {
2603
2709
  // fg color 256 and RGB
2604
2710
  i += this._extractColor(params, i, attr);
@@ -2608,16 +2714,16 @@ export class InputHandler extends Disposable implements IInputHandler {
2608
2714
  } else if (p === 55) {
2609
2715
  // not overline
2610
2716
  attr.bg &= ~BgFlags.OVERLINE;
2717
+ } else if (p === 221 && (this._optionsService.rawOptions.vtExtensions?.kittySgrBoldFaintControl ?? true)) {
2718
+ // not bold (kitty extension)
2719
+ attr.fg &= ~FgFlags.BOLD;
2720
+ } else if (p === 222 && (this._optionsService.rawOptions.vtExtensions?.kittySgrBoldFaintControl ?? true)) {
2721
+ // not faint (kitty extension)
2722
+ attr.bg &= ~BgFlags.DIM;
2611
2723
  } else if (p === 59) {
2612
2724
  attr.extended = attr.extended.clone();
2613
2725
  attr.extended.underlineColor = -1;
2614
2726
  attr.updateExtended();
2615
- } else if (p === 100) { // FIXME: dead branch, p=100 already handled above!
2616
- // reset fg/bg
2617
- attr.fg &= ~(Attributes.CM_MASK | Attributes.RGB_MASK);
2618
- attr.fg |= DEFAULT_ATTR_DATA.fg & (Attributes.PCOLOR_MASK | Attributes.RGB_MASK);
2619
- attr.bg &= ~(Attributes.CM_MASK | Attributes.RGB_MASK);
2620
- attr.bg |= DEFAULT_ATTR_DATA.bg & (Attributes.PCOLOR_MASK | Attributes.RGB_MASK);
2621
2727
  } else {
2622
2728
  this._logService.debug('Unknown SGR attribute: %d.', p);
2623
2729
  }
@@ -2693,6 +2799,12 @@ export class InputHandler extends Disposable implements IInputHandler {
2693
2799
  // no dec locator/mouse
2694
2800
  // this.handler(C0.ESC + '[?50n');
2695
2801
  break;
2802
+ case 996:
2803
+ // color scheme query (https://contour-terminal.org/vt-extensions/color-palette-update-notifications/)
2804
+ if (this._optionsService.rawOptions.vtExtensions?.colorSchemeQuery ?? true) {
2805
+ this._onRequestColorSchemeQuery.fire();
2806
+ }
2807
+ break;
2696
2808
  }
2697
2809
  return true;
2698
2810
  }
@@ -2901,6 +3013,10 @@ export class InputHandler extends Disposable implements IInputHandler {
2901
3013
  this._activeBuffer.savedCurAttrData.fg = this._curAttrData.fg;
2902
3014
  this._activeBuffer.savedCurAttrData.bg = this._curAttrData.bg;
2903
3015
  this._activeBuffer.savedCharset = this._charsetService.charset;
3016
+ this._activeBuffer.savedCharsets = this._charsetService.charsets.slice();
3017
+ this._activeBuffer.savedGlevel = this._charsetService.glevel;
3018
+ this._activeBuffer.savedOriginMode = this._coreService.decPrivateModes.origin;
3019
+ this._activeBuffer.savedWraparoundMode = this._coreService.decPrivateModes.wraparound;
2904
3020
  return true;
2905
3021
  }
2906
3022
 
@@ -2918,15 +3034,16 @@ export class InputHandler extends Disposable implements IInputHandler {
2918
3034
  this._activeBuffer.y = Math.max(this._activeBuffer.savedY - this._activeBuffer.ybase, 0);
2919
3035
  this._curAttrData.fg = this._activeBuffer.savedCurAttrData.fg;
2920
3036
  this._curAttrData.bg = this._activeBuffer.savedCurAttrData.bg;
2921
- this._charsetService.charset = (this as any)._savedCharset;
2922
- if (this._activeBuffer.savedCharset) {
2923
- this._charsetService.charset = this._activeBuffer.savedCharset;
3037
+ for (let i = 0; i < this._activeBuffer.savedCharsets.length; i++) {
3038
+ this._charsetService.setgCharset(i, this._activeBuffer.savedCharsets[i]);
2924
3039
  }
3040
+ this._charsetService.setgLevel(this._activeBuffer.savedGlevel);
3041
+ this._coreService.decPrivateModes.origin = this._activeBuffer.savedOriginMode;
3042
+ this._coreService.decPrivateModes.wraparound = this._activeBuffer.savedWraparoundMode;
2925
3043
  this._restrictCursor();
2926
3044
  return true;
2927
3045
  }
2928
3046
 
2929
-
2930
3047
  /**
2931
3048
  * OSC 2; <data> ST (set window title)
2932
3049
  * Proxy to set window title.
@@ -3249,7 +3366,7 @@ export class InputHandler extends Disposable implements IInputHandler {
3249
3366
  if (collectAndFlag[0] === '/') {
3250
3367
  return true; // TODO: Is this supported?
3251
3368
  }
3252
- this._charsetService.setgCharset(GLEVEL[collectAndFlag[0]], CHARSETS[collectAndFlag[1]] || DEFAULT_CHARSET);
3369
+ this._charsetService.setgCharset(GLEVEL[collectAndFlag[0]], CHARSETS[collectAndFlag[1]] ?? DEFAULT_CHARSET);
3253
3370
  return true;
3254
3371
  }
3255
3372
 
@@ -3320,6 +3437,8 @@ export class InputHandler extends Disposable implements IInputHandler {
3320
3437
  * ESC c
3321
3438
  * DEC mnemonic: RIS (https://vt100.net/docs/vt510-rm/RIS.html)
3322
3439
  * Reset to initial state.
3440
+ *
3441
+ * @vt: #Y ESC RIS "Full Reset" "ESC c" "Reset to initial state."
3323
3442
  */
3324
3443
  public fullReset(): boolean {
3325
3444
  this._parser.reset();
@@ -3436,6 +3555,107 @@ export class InputHandler extends Disposable implements IInputHandler {
3436
3555
  public markRangeDirty(y1: number, y2: number): void {
3437
3556
  this._dirtyRowTracker.markRangeDirty(y1, y2);
3438
3557
  }
3558
+
3559
+ // #region Kitty keyboard
3560
+
3561
+ /**
3562
+ * CSI = flags ; mode u
3563
+ * Set Kitty keyboard protocol flags.
3564
+ * mode: 1=set, 2=set-only-specified, 3=reset-only-specified
3565
+ *
3566
+ * @vt: #Y CSI KKBDSET "Kitty Keyboard Set" "CSI = Ps ; Pm u" "Set Kitty keyboard protocol flags."
3567
+ */
3568
+ public kittyKeyboardSet(params: IParams): boolean {
3569
+ if (!this._optionsService.rawOptions.vtExtensions?.kittyKeyboard) {
3570
+ return true;
3571
+ }
3572
+ const flags = params.params[0] || 0;
3573
+ const mode = params.length > 1 ? (params.params[1] || 1) : 1;
3574
+ const state = this._coreService.kittyKeyboard;
3575
+
3576
+ switch (mode) {
3577
+ case 1: // Set all flags
3578
+ state.flags = flags;
3579
+ break;
3580
+ case 2: // Set only specified flags (OR)
3581
+ state.flags |= flags;
3582
+ break;
3583
+ case 3: // Reset only specified flags (AND NOT)
3584
+ state.flags &= ~flags;
3585
+ break;
3586
+ }
3587
+ return true;
3588
+ }
3589
+
3590
+ /**
3591
+ * CSI ? u
3592
+ * Query Kitty keyboard protocol flags.
3593
+ * Terminal responds with CSI ? flags u
3594
+ *
3595
+ * @vt: #Y CSI KKBDQUERY "Kitty Keyboard Query" "CSI ? u" "Query Kitty keyboard protocol flags."
3596
+ */
3597
+ public kittyKeyboardQuery(params: IParams): boolean {
3598
+ if (!this._optionsService.rawOptions.vtExtensions?.kittyKeyboard) {
3599
+ return true;
3600
+ }
3601
+ const flags = this._coreService.kittyKeyboard.flags;
3602
+ this._coreService.triggerDataEvent(`${C0.ESC}[?${flags}u`);
3603
+ return true;
3604
+ }
3605
+
3606
+ /**
3607
+ * CSI > flags u
3608
+ * Push Kitty keyboard flags onto stack and set new flags.
3609
+ *
3610
+ * @vt: #Y CSI KKBDPUSH "Kitty Keyboard Push" "CSI > Ps u" "Push keyboard flags to stack and set new flags."
3611
+ */
3612
+ public kittyKeyboardPush(params: IParams): boolean {
3613
+ if (!this._optionsService.rawOptions.vtExtensions?.kittyKeyboard) {
3614
+ return true;
3615
+ }
3616
+ const flags = params.params[0] || 0;
3617
+ const state = this._coreService.kittyKeyboard;
3618
+ const isAlt = this._bufferService.buffer === this._bufferService.buffers.alt;
3619
+ const stack = isAlt ? state.altStack : state.mainStack;
3620
+
3621
+ // Evict oldest entry if stack is full (DoS protection, limit of 16)
3622
+ if (stack.length >= 16) {
3623
+ stack.shift();
3624
+ }
3625
+
3626
+ // Push current flags onto stack and set new flags
3627
+ stack.push(state.flags);
3628
+ state.flags = flags;
3629
+ return true;
3630
+ }
3631
+
3632
+ /**
3633
+ * CSI < count u
3634
+ * Pop Kitty keyboard flags from stack.
3635
+ *
3636
+ * @vt: #Y CSI KKBDPOP "Kitty Keyboard Pop" "CSI < Ps u" "Pop keyboard flags from stack."
3637
+ */
3638
+ public kittyKeyboardPop(params: IParams): boolean {
3639
+ if (!this._optionsService.rawOptions.vtExtensions?.kittyKeyboard) {
3640
+ return true;
3641
+ }
3642
+ const count = Math.max(1, params.params[0] || 1);
3643
+ const state = this._coreService.kittyKeyboard;
3644
+ const isAlt = this._bufferService.buffer === this._bufferService.buffers.alt;
3645
+ const stack = isAlt ? state.altStack : state.mainStack;
3646
+
3647
+ // Pop specified number of entries from stack
3648
+ for (let i = 0; i < count && stack.length > 0; i++) {
3649
+ state.flags = stack.pop()!;
3650
+ }
3651
+ // If stack is empty after popping, reset to 0
3652
+ if (stack.length === 0 && count > 0) {
3653
+ state.flags = 0;
3654
+ }
3655
+ return true;
3656
+ }
3657
+
3658
+ // #endregion
3439
3659
  }
3440
3660
 
3441
3661
  export interface IDirtyRowTracker {