@xterm/xterm 6.1.0-beta.30 → 6.1.0-beta.301

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 (181) hide show
  1. package/README.md +69 -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 +56 -45
  8. package/src/browser/AccessibilityManager.ts +18 -13
  9. package/src/browser/Clipboard.ts +8 -5
  10. package/src/browser/ColorContrastCache.ts +3 -3
  11. package/src/browser/CoreBrowserTerminal.ts +180 -350
  12. package/src/browser/Dom.ts +178 -0
  13. package/src/browser/Linkifier.ts +14 -14
  14. package/src/browser/OscLinkProvider.ts +86 -18
  15. package/src/browser/RenderDebouncer.ts +7 -9
  16. package/src/browser/TimeBasedDebouncer.ts +12 -5
  17. package/src/browser/Types.ts +16 -14
  18. package/src/browser/Viewport.ts +58 -23
  19. package/src/browser/decorations/BufferDecorationRenderer.ts +3 -3
  20. package/src/browser/decorations/ColorZoneStore.ts +1 -1
  21. package/src/browser/decorations/OverviewRulerRenderer.ts +36 -20
  22. package/src/browser/input/CompositionHelper.ts +47 -11
  23. package/src/browser/input/Mouse.ts +5 -9
  24. package/src/browser/input/MoveToCell.ts +3 -3
  25. package/src/browser/public/Terminal.ts +33 -36
  26. package/src/browser/renderer/dom/DomRenderer.ts +265 -89
  27. package/src/browser/renderer/dom/DomRendererRowFactory.ts +34 -27
  28. package/src/browser/renderer/dom/WidthCache.ts +57 -55
  29. package/src/browser/renderer/shared/Constants.ts +7 -0
  30. package/src/browser/renderer/shared/RendererUtils.ts +1 -1
  31. package/src/browser/renderer/shared/SelectionRenderModel.ts +2 -2
  32. package/src/browser/renderer/shared/TextBlinkStateManager.ts +97 -0
  33. package/src/browser/renderer/shared/Types.ts +10 -4
  34. package/src/browser/scrollable/abstractScrollbar.ts +300 -0
  35. package/src/browser/scrollable/fastDomNode.ts +126 -0
  36. package/src/browser/scrollable/globalPointerMoveMonitor.ts +90 -0
  37. package/src/browser/scrollable/horizontalScrollbar.ts +85 -0
  38. package/src/browser/scrollable/mouseEvent.ts +292 -0
  39. package/src/browser/scrollable/scrollable.ts +486 -0
  40. package/src/browser/scrollable/scrollableElement.ts +581 -0
  41. package/src/browser/scrollable/scrollableElementOptions.ts +161 -0
  42. package/src/browser/scrollable/scrollbarArrow.ts +110 -0
  43. package/src/browser/scrollable/scrollbarState.ts +246 -0
  44. package/src/browser/scrollable/scrollbarVisibilityController.ts +113 -0
  45. package/src/browser/scrollable/touch.ts +485 -0
  46. package/src/browser/scrollable/verticalScrollbar.ts +143 -0
  47. package/src/browser/scrollable/widget.ts +23 -0
  48. package/src/browser/selection/SelectionModel.ts +4 -3
  49. package/src/browser/services/CharSizeService.ts +4 -4
  50. package/src/browser/services/CharacterJoinerService.ts +13 -11
  51. package/src/browser/services/CoreBrowserService.ts +7 -5
  52. package/src/browser/services/KeyboardService.ts +67 -0
  53. package/src/browser/services/LinkProviderService.ts +3 -3
  54. package/src/browser/services/MouseCoordsService.ts +47 -0
  55. package/src/browser/services/MouseService.ts +610 -23
  56. package/src/browser/services/RenderService.ts +33 -21
  57. package/src/browser/services/SelectionService.ts +73 -55
  58. package/src/browser/services/Services.ts +44 -21
  59. package/src/browser/services/ThemeService.ts +9 -9
  60. package/src/common/Async.ts +141 -0
  61. package/src/common/CircularList.ts +24 -3
  62. package/src/common/Color.ts +13 -5
  63. package/src/common/CoreTerminal.ts +59 -34
  64. package/src/common/Event.ts +118 -0
  65. package/src/common/InputHandler.ts +286 -105
  66. package/src/common/Lifecycle.ts +113 -0
  67. package/src/common/Platform.ts +15 -5
  68. package/src/common/SortedList.ts +8 -4
  69. package/src/common/StringBuilder.ts +67 -0
  70. package/src/common/TaskQueue.ts +17 -8
  71. package/src/common/Types.ts +68 -206
  72. package/src/common/Version.ts +1 -1
  73. package/src/common/WindowsMode.ts +2 -2
  74. package/src/common/buffer/AttributeData.ts +3 -2
  75. package/src/common/buffer/Buffer.ts +47 -32
  76. package/src/common/buffer/BufferLine.ts +175 -100
  77. package/src/common/buffer/BufferLineStringCache.ts +69 -0
  78. package/src/common/buffer/BufferReflow.ts +7 -4
  79. package/src/common/buffer/BufferSet.ts +13 -9
  80. package/src/common/buffer/CellData.ts +61 -4
  81. package/src/common/buffer/Constants.ts +13 -13
  82. package/src/common/buffer/Marker.ts +4 -4
  83. package/src/common/buffer/Types.ts +153 -3
  84. package/src/common/data/Charsets.ts +4 -7
  85. package/src/common/data/EscapeSequences.ts +71 -70
  86. package/src/common/input/Keyboard.ts +17 -10
  87. package/src/common/input/KittyKeyboard.ts +526 -0
  88. package/src/common/input/TextDecoder.ts +3 -3
  89. package/src/common/input/UnicodeV6.ts +3 -2
  90. package/src/common/input/Win32InputMode.ts +297 -0
  91. package/src/common/input/WriteBuffer.ts +108 -39
  92. package/src/common/input/XParseColor.ts +2 -2
  93. package/src/common/parser/ApcParser.ts +196 -0
  94. package/src/common/parser/Constants.ts +14 -4
  95. package/src/common/parser/DcsParser.ts +15 -16
  96. package/src/common/parser/EscapeSequenceParser.ts +214 -72
  97. package/src/common/parser/OscParser.ts +14 -15
  98. package/src/common/parser/Params.ts +31 -12
  99. package/src/common/parser/Types.ts +40 -30
  100. package/src/common/public/BufferApiView.ts +3 -3
  101. package/src/common/public/BufferLineApiView.ts +4 -4
  102. package/src/common/public/BufferNamespaceApi.ts +5 -5
  103. package/src/common/public/ParserApi.ts +5 -2
  104. package/src/common/public/UnicodeApi.ts +1 -1
  105. package/src/common/services/BufferService.ts +17 -13
  106. package/src/common/services/CharsetService.ts +6 -2
  107. package/src/common/services/CoreService.ts +23 -10
  108. package/src/common/services/DecorationService.ts +260 -15
  109. package/src/common/services/InstantiationService.ts +2 -2
  110. package/src/common/services/LogService.ts +2 -32
  111. package/src/common/services/{CoreMouseService.ts → MouseStateService.ts} +22 -133
  112. package/src/common/services/OptionsService.ts +17 -7
  113. package/src/common/services/OscLinkService.ts +3 -2
  114. package/src/common/services/ServiceRegistry.ts +14 -8
  115. package/src/common/services/Services.ts +54 -50
  116. package/src/common/services/UnicodeService.ts +6 -11
  117. package/typings/xterm.d.ts +329 -34
  118. package/src/common/Clone.ts +0 -23
  119. package/src/common/TypedArrayUtils.ts +0 -17
  120. package/src/vs/base/browser/browser.ts +0 -141
  121. package/src/vs/base/browser/canIUse.ts +0 -49
  122. package/src/vs/base/browser/dom.ts +0 -2369
  123. package/src/vs/base/browser/fastDomNode.ts +0 -316
  124. package/src/vs/base/browser/globalPointerMoveMonitor.ts +0 -112
  125. package/src/vs/base/browser/iframe.ts +0 -135
  126. package/src/vs/base/browser/keyboardEvent.ts +0 -213
  127. package/src/vs/base/browser/mouseEvent.ts +0 -229
  128. package/src/vs/base/browser/touch.ts +0 -372
  129. package/src/vs/base/browser/ui/scrollbar/abstractScrollbar.ts +0 -303
  130. package/src/vs/base/browser/ui/scrollbar/horizontalScrollbar.ts +0 -114
  131. package/src/vs/base/browser/ui/scrollbar/scrollableElement.ts +0 -720
  132. package/src/vs/base/browser/ui/scrollbar/scrollableElementOptions.ts +0 -165
  133. package/src/vs/base/browser/ui/scrollbar/scrollbarArrow.ts +0 -114
  134. package/src/vs/base/browser/ui/scrollbar/scrollbarState.ts +0 -243
  135. package/src/vs/base/browser/ui/scrollbar/scrollbarVisibilityController.ts +0 -118
  136. package/src/vs/base/browser/ui/scrollbar/verticalScrollbar.ts +0 -116
  137. package/src/vs/base/browser/ui/widget.ts +0 -57
  138. package/src/vs/base/browser/window.ts +0 -14
  139. package/src/vs/base/common/arrays.ts +0 -887
  140. package/src/vs/base/common/arraysFind.ts +0 -202
  141. package/src/vs/base/common/assert.ts +0 -71
  142. package/src/vs/base/common/async.ts +0 -1992
  143. package/src/vs/base/common/cancellation.ts +0 -148
  144. package/src/vs/base/common/charCode.ts +0 -450
  145. package/src/vs/base/common/collections.ts +0 -140
  146. package/src/vs/base/common/decorators.ts +0 -130
  147. package/src/vs/base/common/equals.ts +0 -146
  148. package/src/vs/base/common/errors.ts +0 -303
  149. package/src/vs/base/common/event.ts +0 -1778
  150. package/src/vs/base/common/functional.ts +0 -32
  151. package/src/vs/base/common/hash.ts +0 -316
  152. package/src/vs/base/common/iterator.ts +0 -159
  153. package/src/vs/base/common/keyCodes.ts +0 -526
  154. package/src/vs/base/common/keybindings.ts +0 -284
  155. package/src/vs/base/common/lazy.ts +0 -47
  156. package/src/vs/base/common/lifecycle.ts +0 -801
  157. package/src/vs/base/common/linkedList.ts +0 -142
  158. package/src/vs/base/common/map.ts +0 -202
  159. package/src/vs/base/common/numbers.ts +0 -98
  160. package/src/vs/base/common/observable.ts +0 -76
  161. package/src/vs/base/common/observableInternal/api.ts +0 -31
  162. package/src/vs/base/common/observableInternal/autorun.ts +0 -281
  163. package/src/vs/base/common/observableInternal/base.ts +0 -489
  164. package/src/vs/base/common/observableInternal/debugName.ts +0 -145
  165. package/src/vs/base/common/observableInternal/derived.ts +0 -428
  166. package/src/vs/base/common/observableInternal/lazyObservableValue.ts +0 -146
  167. package/src/vs/base/common/observableInternal/logging.ts +0 -328
  168. package/src/vs/base/common/observableInternal/promise.ts +0 -209
  169. package/src/vs/base/common/observableInternal/utils.ts +0 -610
  170. package/src/vs/base/common/platform.ts +0 -281
  171. package/src/vs/base/common/scrollable.ts +0 -522
  172. package/src/vs/base/common/sequence.ts +0 -34
  173. package/src/vs/base/common/stopwatch.ts +0 -43
  174. package/src/vs/base/common/strings.ts +0 -557
  175. package/src/vs/base/common/symbols.ts +0 -9
  176. package/src/vs/base/common/uint.ts +0 -59
  177. package/src/vs/patches/nls.ts +0 -90
  178. package/src/vs/typings/base-common.d.ts +0 -20
  179. package/src/vs/typings/require.d.ts +0 -42
  180. package/src/vs/typings/vscode-globals-nls.d.ts +0 -36
  181. package/src/vs/typings/vscode-globals-product.d.ts +0 -33
@@ -21,43 +21,44 @@
21
21
  * http://linux.die.net/man/7/urxvt
22
22
  */
23
23
 
24
- import { IDecoration, IDecorationOptions, IDisposable, ILinkProvider, IMarker } from '@xterm/xterm';
25
- import { copyHandler, handlePasteEvent, moveTextAreaUnderMouseCursor, paste, rightClickHandler } from 'browser/Clipboard';
26
- import * as Strings from 'browser/LocalizableStrings';
27
- import { OscLinkProvider } from 'browser/OscLinkProvider';
28
- import { CharacterJoinerHandler, CustomKeyEventHandler, CustomWheelEventHandler, IBrowser, IBufferRange, ICompositionHelper, ILinkifier2, ITerminal } from 'browser/Types';
29
- import { Viewport } from 'browser/Viewport';
30
- import { BufferDecorationRenderer } from 'browser/decorations/BufferDecorationRenderer';
31
- import { OverviewRulerRenderer } from 'browser/decorations/OverviewRulerRenderer';
32
- import { CompositionHelper } from 'browser/input/CompositionHelper';
33
- import { DomRenderer } from 'browser/renderer/dom/DomRenderer';
34
- import { IRenderer } from 'browser/renderer/shared/Types';
35
- import { CharSizeService } from 'browser/services/CharSizeService';
36
- import { CharacterJoinerService } from 'browser/services/CharacterJoinerService';
37
- import { CoreBrowserService } from 'browser/services/CoreBrowserService';
38
- import { LinkProviderService } from 'browser/services/LinkProviderService';
39
- import { MouseService } from 'browser/services/MouseService';
40
- import { RenderService } from 'browser/services/RenderService';
41
- import { SelectionService } from 'browser/services/SelectionService';
42
- import { ICharSizeService, ICharacterJoinerService, ICoreBrowserService, ILinkProviderService, IMouseService, IRenderService, ISelectionService, IThemeService } from 'browser/services/Services';
43
- import { ThemeService } from 'browser/services/ThemeService';
44
- import { channels, color } from 'common/Color';
45
- import { CoreTerminal } from 'common/CoreTerminal';
46
- import * as Browser from 'common/Platform';
47
- import { ColorRequestType, CoreMouseAction, CoreMouseButton, CoreMouseEventType, IColorEvent, ITerminalOptions, KeyboardResultType, SpecialColorIndex } from 'common/Types';
48
- import { DEFAULT_ATTR_DATA } from 'common/buffer/BufferLine';
49
- import { IBuffer } from 'common/buffer/Types';
50
- import { C0, C1_ESCAPED } from 'common/data/EscapeSequences';
51
- import { evaluateKeyboardEvent } from 'common/input/Keyboard';
52
- import { toRgbString } from 'common/input/XParseColor';
53
- import { DecorationService } from 'common/services/DecorationService';
54
- import { IDecorationService } from 'common/services/Services';
24
+ import { IDecoration, IDecorationOptions, IDisposable, ILinkProvider, IMarker, IRenderDimensions as IRenderDimensionsApi } from '@xterm/xterm';
25
+ import { copyHandler, handlePasteEvent, moveTextAreaUnderMouseCursor, paste, rightClickHandler } from './Clipboard';
26
+ import * as Strings from './LocalizableStrings';
27
+ import { OscLinkProvider } from './OscLinkProvider';
28
+ import { CharacterJoinerHandler, CustomKeyEventHandler, CustomWheelEventHandler, IBrowser, IBufferRange, ICompositionHelper, ILinkifier2, ITerminal } from './Types';
29
+ import { Viewport } from './Viewport';
30
+ import { BufferDecorationRenderer } from './decorations/BufferDecorationRenderer';
31
+ import { OverviewRulerRenderer } from './decorations/OverviewRulerRenderer';
32
+ import { CompositionHelper } from './input/CompositionHelper';
33
+ import { DomRenderer } from './renderer/dom/DomRenderer';
34
+ import { IRenderer } from './renderer/shared/Types';
35
+ import { CharSizeService } from './services/CharSizeService';
36
+ import { CharacterJoinerService } from './services/CharacterJoinerService';
37
+ import { CoreBrowserService } from './services/CoreBrowserService';
38
+ import { LinkProviderService } from './services/LinkProviderService';
39
+ import { MouseCoordsService } from './services/MouseCoordsService';
40
+ import { MouseEventCssClasses, MouseService } from './services/MouseService';
41
+ import { RenderService } from './services/RenderService';
42
+ import { SelectionService } from './services/SelectionService';
43
+ import { ICharSizeService, ICharacterJoinerService, ICoreBrowserService, IKeyboardService, ILinkProviderService, IMouseCoordsService, IMouseService, IRenderService, ISelectionService, IThemeService } from './services/Services';
44
+ import { ThemeService } from './services/ThemeService';
45
+ import { KeyboardService } from './services/KeyboardService';
46
+ import { channels, color, rgb } from '../common/Color';
47
+ import { CoreTerminal } from '../common/CoreTerminal';
48
+ import * as Browser from '../common/Platform';
49
+ import { ColorRequestType, IColorEvent, ITerminalOptions, KeyboardResultType, SpecialColorIndex } from '../common/Types';
50
+ import { DEFAULT_ATTR_DATA } from '../common/buffer/BufferLine';
51
+ import { IBuffer } from '../common/buffer/Types';
52
+ import { C0, C1ESCAPED } from '../common/data/EscapeSequences';
53
+ import { toRgbString } from '../common/input/XParseColor';
54
+ import { DecorationService } from '../common/services/DecorationService';
55
+ import { IDecorationService } from '../common/services/Services';
55
56
  import { WindowsOptionsReportType } from '../common/InputHandler';
56
57
  import { AccessibilityManager } from './AccessibilityManager';
57
58
  import { Linkifier } from './Linkifier';
58
- import { Emitter, Event } from 'vs/base/common/event';
59
- import { addDisposableListener } from 'vs/base/browser/dom';
60
- import { MutableDisposable, toDisposable } from 'vs/base/common/lifecycle';
59
+ import { Emitter, EventUtils, type IEvent } from '../common/Event';
60
+ import { addDisposableListener } from './Dom';
61
+ import { MutableDisposable, toDisposable } from '../common/Lifecycle';
61
62
 
62
63
  export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
63
64
  public textarea: HTMLTextAreaElement | undefined;
@@ -77,15 +78,16 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
77
78
  public browser: IBrowser = Browser as any;
78
79
 
79
80
  private _customKeyEventHandler: CustomKeyEventHandler | undefined;
80
- private _customWheelEventHandler: CustomWheelEventHandler | undefined;
81
81
 
82
82
  // Browser services
83
- private _decorationService: DecorationService;
84
- private _linkProviderService: ILinkProviderService;
83
+ private readonly _decorationService: DecorationService;
84
+ private readonly _keyboardService: IKeyboardService;
85
+ private readonly _linkProviderService: ILinkProviderService;
85
86
 
86
87
  // Optional browser services
87
88
  private _charSizeService: ICharSizeService | undefined;
88
89
  private _coreBrowserService: ICoreBrowserService | undefined;
90
+ private _mouseCoordsService: IMouseCoordsService | undefined;
89
91
  private _mouseService: IMouseService | undefined;
90
92
  private _renderService: IRenderService | undefined;
91
93
  private _themeService: IThemeService | undefined;
@@ -100,7 +102,7 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
100
102
  private _keyDownHandled: boolean = false;
101
103
 
102
104
  /**
103
- * Records whether a keydown event has occured since the last keyup event, i.e. whether a key
105
+ * Records whether a keydown event has occurred since the last keyup event, i.e. whether a key
104
106
  * is currently "pressed".
105
107
  */
106
108
  private _keyDownSeen: boolean = false;
@@ -134,15 +136,35 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
134
136
  public readonly onBell = this._onBell.event;
135
137
 
136
138
  private _onFocus = this._register(new Emitter<void>());
137
- public get onFocus(): Event<void> { return this._onFocus.event; }
139
+ public get onFocus(): IEvent<void> { return this._onFocus.event; }
138
140
  private _onBlur = this._register(new Emitter<void>());
139
- public get onBlur(): Event<void> { return this._onBlur.event; }
141
+ public get onBlur(): IEvent<void> { return this._onBlur.event; }
140
142
  private _onA11yCharEmitter = this._register(new Emitter<string>());
141
- public get onA11yChar(): Event<string> { return this._onA11yCharEmitter.event; }
143
+ public get onA11yChar(): IEvent<string> { return this._onA11yCharEmitter.event; }
142
144
  private _onA11yTabEmitter = this._register(new Emitter<number>());
143
- public get onA11yTab(): Event<number> { return this._onA11yTabEmitter.event; }
145
+ public get onA11yTab(): IEvent<number> { return this._onA11yTabEmitter.event; }
144
146
  private _onWillOpen = this._register(new Emitter<HTMLElement>());
145
- public get onWillOpen(): Event<HTMLElement> { return this._onWillOpen.event; }
147
+ public get onWillOpen(): IEvent<HTMLElement> { return this._onWillOpen.event; }
148
+ private readonly _onDimensionsChange = this._register(new Emitter<IRenderDimensionsApi>());
149
+ public readonly onDimensionsChange = this._onDimensionsChange.event;
150
+
151
+ public get dimensions(): IRenderDimensionsApi | undefined {
152
+ if (!this._renderService) {
153
+ return undefined;
154
+ }
155
+ const dimensions = this._renderService.dimensions;
156
+ return {
157
+ css: {
158
+ canvas: { ...dimensions.css.canvas },
159
+ cell: { ...dimensions.css.cell }
160
+ },
161
+ device: {
162
+ canvas: { ...dimensions.device.canvas },
163
+ cell: { ...dimensions.device.cell },
164
+ char: { ...dimensions.device.char }
165
+ }
166
+ };
167
+ }
146
168
 
147
169
  constructor(
148
170
  options: Partial<ITerminalOptions> = {}
@@ -153,6 +175,8 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
153
175
 
154
176
  this._decorationService = this._instantiationService.createInstance(DecorationService);
155
177
  this._instantiationService.setService(IDecorationService, this._decorationService);
178
+ this._keyboardService = this._instantiationService.createInstance(KeyboardService);
179
+ this._instantiationService.setService(IKeyboardService, this._keyboardService);
156
180
  this._linkProviderService = this._instantiationService.createInstance(LinkProviderService);
157
181
  this._instantiationService.setService(ILinkProviderService, this._linkProviderService);
158
182
  this._linkProviderService.registerLinkProvider(this._instantiationService.createInstance(OscLinkProvider));
@@ -164,10 +188,10 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
164
188
  this._register(this._inputHandler.onRequestReset(() => this.reset()));
165
189
  this._register(this._inputHandler.onRequestWindowsOptionsReport(type => this._reportWindowsOptions(type)));
166
190
  this._register(this._inputHandler.onColor((event) => this._handleColorEvent(event)));
167
- this._register(Event.forward(this._inputHandler.onCursorMove, this._onCursorMove));
168
- this._register(Event.forward(this._inputHandler.onTitleChange, this._onTitleChange));
169
- this._register(Event.forward(this._inputHandler.onA11yChar, this._onA11yCharEmitter));
170
- this._register(Event.forward(this._inputHandler.onA11yTab, this._onA11yTabEmitter));
191
+ this._register(EventUtils.forward(this._inputHandler.onCursorMove, this._onCursorMove));
192
+ this._register(EventUtils.forward(this._inputHandler.onTitleChange, this._onTitleChange));
193
+ this._register(EventUtils.forward(this._inputHandler.onA11yChar, this._onA11yCharEmitter));
194
+ this._register(EventUtils.forward(this._inputHandler.onA11yTab, this._onA11yTabEmitter));
171
195
 
172
196
  // Setup listeners
173
197
  this._register(this._bufferService.onResize(e => this._afterResize(e.cols, e.rows)));
@@ -188,7 +212,7 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
188
212
  if (!this._themeService) return;
189
213
  for (const req of event) {
190
214
  let acc: 'foreground' | 'background' | 'cursor' | 'ansi';
191
- let ident = '';
215
+ let ident: string;
192
216
  switch (req.index) {
193
217
  case SpecialColorIndex.FOREGROUND: // OSC 10 | 110
194
218
  acc = 'foreground';
@@ -212,7 +236,7 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
212
236
  const colorRgb = color.toColorRGB(acc === 'ansi'
213
237
  ? this._themeService.colors.ansi[req.index]
214
238
  : this._themeService.colors[acc]);
215
- this.coreService.triggerDataEvent(`${C0.ESC}]${ident};${toRgbString(colorRgb)}${C1_ESCAPED.ST}`);
239
+ this.coreService.triggerDataEvent(`${C0.ESC}]${ident};${toRgbString(colorRgb)}${C1ESCAPED.ST}`);
216
240
  break;
217
241
  case ColorRequestType.SET:
218
242
  if (acc === 'ansi') {
@@ -229,6 +253,20 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
229
253
  }
230
254
  }
231
255
 
256
+ /**
257
+ * Reports the current color scheme (dark or light) based on the relative luminance
258
+ * of the background and foreground theme colors.
259
+ * Sends CSI ? 997 ; 1 n for dark mode or CSI ? 997 ; 2 n for light mode.
260
+ */
261
+ private _reportColorScheme(): void {
262
+ if (!this._themeService) return;
263
+ const bgLuminance = rgb.relativeLuminance(this._themeService.colors.background.rgba >> 8);
264
+ const fgLuminance = rgb.relativeLuminance(this._themeService.colors.foreground.rgba >> 8);
265
+ // Dark mode = background is darker than foreground (lower luminance)
266
+ const colorSchemeMode = bgLuminance < fgLuminance ? 1 : 2;
267
+ this.coreService.triggerDataEvent(`${C0.ESC}[?997;${colorSchemeMode}n`);
268
+ }
269
+
232
270
  protected _setup(): void {
233
271
  super._setup();
234
272
 
@@ -376,7 +414,16 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
376
414
  this._register(addDisposableListener(this.textarea!, 'keyup', (ev: KeyboardEvent) => this._keyUp(ev), true));
377
415
  this._register(addDisposableListener(this.textarea!, 'keydown', (ev: KeyboardEvent) => this._keyDown(ev), true));
378
416
  this._register(addDisposableListener(this.textarea!, 'keypress', (ev: KeyboardEvent) => this._keyPress(ev), true));
379
- this._register(addDisposableListener(this.textarea!, 'compositionstart', () => this._compositionHelper!.compositionstart()));
417
+ this._register(addDisposableListener(this.textarea!, 'compositionstart', () => {
418
+ // Ensure the textarea is synced to the latest cursor location before composition begins. This
419
+ // is to workaround a problem where highly dynamic TUIs like agentic CLIs reprint agressively
420
+ // would cause the IME to appear in the wrong position. The theory is that when the IME is
421
+ // triggered during a partial render the textarea position becomes locked and will not move
422
+ // until it is hidden and a custom move occurs.
423
+ this._syncTextArea();
424
+ this._compositionHelper!.compositionstart();
425
+ this._compositionHelper!.updateCompositionElements();
426
+ }));
380
427
  this._register(addDisposableListener(this.textarea!, 'compositionupdate', (e: CompositionEvent) => this._compositionHelper!.compositionupdate(e)));
381
428
  this._register(addDisposableListener(this.textarea!, 'compositionend', () => this._compositionHelper!.compositionend()));
382
429
  this._register(addDisposableListener(this.textarea!, 'input', (ev: InputEvent) => this._inputEvent(ev), true));
@@ -416,6 +463,8 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
416
463
  this.element.dir = 'ltr'; // xterm.css assumes LTR
417
464
  this.element.classList.add('terminal');
418
465
  this.element.classList.add('xterm');
466
+ this.element.classList.toggle('allow-transparency', this.options.allowTransparency);
467
+ this._register(this.optionsService.onSpecificOptionChange('allowTransparency', value => this.element!.classList.toggle('allow-transparency', value)));
419
468
  parent.appendChild(this.element);
420
469
 
421
470
  // Performance: Use a document fragment to build the terminal
@@ -443,6 +492,7 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
443
492
  // https://issuetracker.google.com/issues/260170397
444
493
  this.textarea.setAttribute('aria-multiline', 'false');
445
494
  }
495
+ this.textarea.setAttribute('autocomplete', 'off');
446
496
  this.textarea.setAttribute('autocorrect', 'off');
447
497
  this.textarea.setAttribute('autocapitalize', 'off');
448
498
  this.textarea.setAttribute('spellcheck', 'false');
@@ -456,7 +506,7 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
456
506
  this.textarea,
457
507
  parent.ownerDocument.defaultView ?? window,
458
508
  // Force unsafe null in node.js environment for tests
459
- this._document ?? (typeof window !== 'undefined') ? window.document : null as any
509
+ this._document ?? ((typeof window !== 'undefined') ? window.document : null as any)
460
510
  ));
461
511
  this._instantiationService.setService(ICoreBrowserService, this._coreBrowserService);
462
512
 
@@ -470,12 +520,33 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
470
520
  this._themeService = this._instantiationService.createInstance(ThemeService);
471
521
  this._instantiationService.setService(IThemeService, this._themeService);
472
522
 
523
+ // CSI ? 996 n - color scheme query (https://contour-terminal.org/vt-extensions/color-palette-update-notifications/)
524
+ this._register(this._inputHandler.onRequestColorSchemeQuery(() => this._reportColorScheme()));
525
+
526
+ // Emit unsolicited color scheme notification on theme change when DECSET 2031 is enabled
527
+ this._register(this._themeService.onChangeColors(() => {
528
+ if (this.coreService.decPrivateModes.colorSchemeUpdates) {
529
+ this._reportColorScheme();
530
+ }
531
+ }));
532
+
473
533
  this._characterJoinerService = this._instantiationService.createInstance(CharacterJoinerService);
474
534
  this._instantiationService.setService(ICharacterJoinerService, this._characterJoinerService);
475
535
 
476
536
  this._renderService = this._register(this._instantiationService.createInstance(RenderService, this.rows, this.screenElement));
477
537
  this._instantiationService.setService(IRenderService, this._renderService);
478
538
  this._register(this._renderService.onRenderedViewportChange(e => this._onRender.fire(e)));
539
+ this._register(this._renderService.onDimensionsChange(e => this._onDimensionsChange.fire({
540
+ css: {
541
+ canvas: { ...e.css.canvas },
542
+ cell: { ...e.css.cell }
543
+ },
544
+ device: {
545
+ canvas: { ...e.device.canvas },
546
+ cell: { ...e.device.cell },
547
+ char: { ...e.device.char }
548
+ }
549
+ })));
479
550
  this.onResize(e => this._renderService!.resize(e.cols, e.rows));
480
551
 
481
552
  this._compositionView = this._document.createElement('div');
@@ -483,8 +554,8 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
483
554
  this._compositionHelper = this._instantiationService.createInstance(CompositionHelper, this.textarea, this._compositionView);
484
555
  this._helperContainer.appendChild(this._compositionView);
485
556
 
486
- this._mouseService = this._instantiationService.createInstance(MouseService);
487
- this._instantiationService.setService(IMouseService, this._mouseService);
557
+ this._mouseCoordsService = this._instantiationService.createInstance(MouseCoordsService);
558
+ this._instantiationService.setService(IMouseCoordsService, this._mouseCoordsService);
488
559
 
489
560
  const linkifier = this._linkifier.value = this._register(this._instantiationService.createInstance(Linkifier, this.screenElement));
490
561
 
@@ -493,8 +564,9 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
493
564
 
494
565
  try {
495
566
  this._onWillOpen.fire(this.element);
567
+ } catch (e) {
568
+ this._logService.error('onWillOpen handler threw an exception', e);
496
569
  }
497
- catch { /* fails to load addon for some reason */ }
498
570
  if (!this._renderService.hasRenderer()) {
499
571
  this._renderService.setRenderer(this._createRenderer());
500
572
  }
@@ -503,7 +575,10 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
503
575
  this._renderService!.handleCursorMove();
504
576
  this._syncTextArea();
505
577
  }));
506
- this._register(this.onResize(() => this._renderService!.handleResize(this.cols, this.rows)));
578
+ this._register(this.onResize(() => {
579
+ this._renderService!.handleResize(this.cols, this.rows);
580
+ this._syncTextArea();
581
+ }));
507
582
  this._register(this.onBlur(() => this._renderService!.handleBlur()));
508
583
  this._register(this.onFocus(() => this._renderService!.handleFocus()));
509
584
 
@@ -519,6 +594,8 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
519
594
  linkifier
520
595
  ));
521
596
  this._instantiationService.setService(ISelectionService, this._selectionService);
597
+ this._mouseService = this._instantiationService.createInstance(MouseService);
598
+ this._instantiationService.setService(IMouseService, this._mouseService);
522
599
  this._register(this._selectionService.onRequestScrollLines(e => this.scrollLines(e.amount, e.suppressScrollEvent)));
523
600
  this._register(this._selectionService.onSelectionChange(() => this._onSelectionChange.fire()));
524
601
  this._register(this._selectionService.onRequestRedraw(e => this._renderService!.handleSelectionChanged(e.start, e.end, e.columnSelectMode)));
@@ -530,7 +607,7 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
530
607
  this.textarea!.focus();
531
608
  this.textarea!.select();
532
609
  }));
533
- this._register(Event.any(
610
+ this._register(EventUtils.any(
534
611
  this._onScroll.event,
535
612
  this._inputHandler.onScroll
536
613
  )(() => {
@@ -542,11 +619,12 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
542
619
  this._register(addDisposableListener(this.element, 'mousedown', (e: MouseEvent) => this._selectionService!.handleMouseDown(e)));
543
620
 
544
621
  // apply mouse event classes set by escape codes before terminal was attached
545
- if (this.coreMouseService.areMouseEventsActive) {
622
+ if (this.mouseStateService.areMouseEventsActive && !this.options.mouseEventsRequireAlt) {
546
623
  this._selectionService.disable();
547
- this.element.classList.add('enable-mouse-events');
624
+ this.element.classList.add(MouseEventCssClasses.ENABLE_MOUSE_EVENTS);
548
625
  } else {
549
626
  this._selectionService.enable();
627
+ this.element.classList.remove(MouseEventCssClasses.ENABLE_MOUSE_EVENTS);
550
628
  }
551
629
 
552
630
  if (this.options.screenReaderMode) {
@@ -556,11 +634,14 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
556
634
  }
557
635
  this._register(this.optionsService.onSpecificOptionChange('screenReaderMode', e => this._handleScreenReaderModeOptionChange(e)));
558
636
 
559
- if (this.options.overviewRuler.width) {
637
+ const showScrollbar = this.options.scrollbar?.showScrollbar ?? true;
638
+ const overviewRulerWidth = this.options.scrollbar?.width;
639
+ if (showScrollbar && overviewRulerWidth) {
560
640
  this._overviewRulerRenderer = this._register(this._instantiationService.createInstance(OverviewRulerRenderer, this._viewportElement, this.screenElement));
561
641
  }
562
- this.optionsService.onSpecificOptionChange('overviewRuler', value => {
563
- if (!this._overviewRulerRenderer && value && this._viewportElement && this.screenElement) {
642
+ this.optionsService.onSpecificOptionChange('scrollbar', value => {
643
+ const shouldShow = (value?.showScrollbar ?? true) && !!value?.width;
644
+ if (!this._overviewRulerRenderer && shouldShow && this._viewportElement && this.screenElement) {
564
645
  this._overviewRulerRenderer = this._register(this._instantiationService.createInstance(OverviewRulerRenderer, this._viewportElement, this.screenElement));
565
646
  }
566
647
  });
@@ -575,280 +656,26 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
575
656
 
576
657
  // Listen for mouse events and translate
577
658
  // them into terminal mouse protocols.
578
- this.bindMouse();
659
+ this._mouseService.bindMouse({
660
+ element: this.element!,
661
+ screenElement: this.screenElement!,
662
+ document: this._document!,
663
+ handleTouchScroll: amount => this._viewport?.handleTouchScroll(amount)
664
+ }, disposable => this._register(disposable), () => this.focus());
579
665
  }
580
666
 
581
667
  private _createRenderer(): IRenderer {
582
668
  return this._instantiationService.createInstance(DomRenderer, this, this._document!, this.element!, this.screenElement!, this._viewportElement!, this._helperContainer!, this.linkifier!);
583
669
  }
584
670
 
585
- /**
586
- * Bind certain mouse events to the terminal.
587
- * By default only 3 button + wheel up/down is ativated. For higher buttons
588
- * no mouse report will be created. Typically the standard actions will be active.
589
- *
590
- * There are several reasons not to enable support for higher buttons/wheel:
591
- * - Button 4 and 5 are typically used for history back and forward navigation,
592
- * there is no straight forward way to supress/intercept those standard actions.
593
- * - Support for higher buttons does not work in some platform/browser combinations.
594
- * - Left/right wheel was not tested.
595
- * - Emulators vary in mouse button support, typically only 3 buttons and
596
- * wheel up/down work reliable.
597
- *
598
- * TODO: Move mouse event code into its own file.
599
- */
600
- public bindMouse(): void {
601
- const self = this;
602
- const el = this.element!;
603
-
604
- // send event to CoreMouseService
605
- function sendEvent(ev: MouseEvent | WheelEvent): boolean {
606
- // get mouse coordinates
607
- const pos = self._mouseService!.getMouseReportCoords(ev, self.screenElement!);
608
- if (!pos) {
609
- return false;
610
- }
611
-
612
- let but: CoreMouseButton;
613
- let action: CoreMouseAction | undefined;
614
- switch ((ev as any).overrideType || ev.type) {
615
- case 'mousemove':
616
- action = CoreMouseAction.MOVE;
617
- if (ev.buttons === undefined) {
618
- // buttons is not supported on macOS, try to get a value from button instead
619
- but = CoreMouseButton.NONE;
620
- if (ev.button !== undefined) {
621
- but = ev.button < 3 ? ev.button : CoreMouseButton.NONE;
622
- }
623
- } else {
624
- // according to MDN buttons only reports up to button 5 (AUX2)
625
- but = ev.buttons & 1 ? CoreMouseButton.LEFT :
626
- ev.buttons & 4 ? CoreMouseButton.MIDDLE :
627
- ev.buttons & 2 ? CoreMouseButton.RIGHT :
628
- CoreMouseButton.NONE; // fallback to NONE
629
- }
630
- break;
631
- case 'mouseup':
632
- action = CoreMouseAction.UP;
633
- but = ev.button < 3 ? ev.button : CoreMouseButton.NONE;
634
- break;
635
- case 'mousedown':
636
- action = CoreMouseAction.DOWN;
637
- but = ev.button < 3 ? ev.button : CoreMouseButton.NONE;
638
- break;
639
- case 'wheel':
640
- if (self._customWheelEventHandler && self._customWheelEventHandler(ev as WheelEvent) === false) {
641
- return false;
642
- }
643
- const deltaY = (ev as WheelEvent).deltaY;
644
- if (deltaY === 0) {
645
- return false;
646
- }
647
- const lines = self.coreMouseService.consumeWheelEvent(
648
- ev as WheelEvent,
649
- self._renderService?.dimensions?.device?.cell?.height,
650
- self._coreBrowserService?.dpr
651
- );
652
- if (lines === 0) {
653
- return false;
654
- }
655
- action = deltaY < 0 ? CoreMouseAction.UP : CoreMouseAction.DOWN;
656
- but = CoreMouseButton.WHEEL;
657
- break;
658
- default:
659
- // dont handle other event types by accident
660
- return false;
661
- }
662
-
663
- // exit if we cannot determine valid button/action values
664
- // do nothing for higher buttons than wheel
665
- if (action === undefined || but === undefined || but > CoreMouseButton.WHEEL) {
666
- return false;
667
- }
668
-
669
- return self.coreMouseService.triggerMouseEvent({
670
- col: pos.col,
671
- row: pos.row,
672
- x: pos.x,
673
- y: pos.y,
674
- button: but,
675
- action,
676
- ctrl: ev.ctrlKey,
677
- alt: ev.altKey,
678
- shift: ev.shiftKey
679
- });
680
- }
681
-
682
- /**
683
- * Event listener state handling.
684
- * We listen to the onProtocolChange event of CoreMouseService and put
685
- * requested listeners in `requestedEvents`. With this the listeners
686
- * have all bits to do the event listener juggling.
687
- * Note: 'mousedown' currently is "always on" and not managed
688
- * by onProtocolChange.
689
- */
690
- const requestedEvents: { [key: string]: ((ev: MouseEvent | WheelEvent) => void) | null } = {
691
- mouseup: null,
692
- wheel: null,
693
- mousedrag: null,
694
- mousemove: null
695
- };
696
- const eventListeners: { [key: string]: (ev: any) => void | boolean } = {
697
- mouseup: (ev: MouseEvent) => {
698
- sendEvent(ev);
699
- if (!ev.buttons) {
700
- // if no other button is held remove global handlers
701
- this._document!.removeEventListener('mouseup', requestedEvents.mouseup!);
702
- if (requestedEvents.mousedrag) {
703
- this._document!.removeEventListener('mousemove', requestedEvents.mousedrag);
704
- }
705
- }
706
- return this.cancel(ev);
707
- },
708
- wheel: (ev: WheelEvent) => {
709
- sendEvent(ev);
710
- return this.cancel(ev, true);
711
- },
712
- mousedrag: (ev: MouseEvent) => {
713
- // deal only with move while a button is held
714
- if (ev.buttons) {
715
- sendEvent(ev);
716
- }
717
- },
718
- mousemove: (ev: MouseEvent) => {
719
- // deal only with move without any button
720
- if (!ev.buttons) {
721
- sendEvent(ev);
722
- }
723
- }
724
- };
725
- this._register(this.coreMouseService.onProtocolChange(events => {
726
- // apply global changes on events
727
- if (events) {
728
- if (this.optionsService.rawOptions.logLevel === 'debug') {
729
- this._logService.debug('Binding to mouse events:', this.coreMouseService.explainEvents(events));
730
- }
731
- this.element!.classList.add('enable-mouse-events');
732
- this._selectionService!.disable();
733
- } else {
734
- this._logService.debug('Unbinding from mouse events.');
735
- this.element!.classList.remove('enable-mouse-events');
736
- this._selectionService!.enable();
737
- }
738
-
739
- // add/remove handlers from requestedEvents
740
-
741
- if (!(events & CoreMouseEventType.MOVE)) {
742
- el.removeEventListener('mousemove', requestedEvents.mousemove!);
743
- requestedEvents.mousemove = null;
744
- } else if (!requestedEvents.mousemove) {
745
- el.addEventListener('mousemove', eventListeners.mousemove);
746
- requestedEvents.mousemove = eventListeners.mousemove;
747
- }
748
-
749
- if (!(events & CoreMouseEventType.WHEEL)) {
750
- el.removeEventListener('wheel', requestedEvents.wheel!);
751
- requestedEvents.wheel = null;
752
- } else if (!requestedEvents.wheel) {
753
- el.addEventListener('wheel', eventListeners.wheel, { passive: false });
754
- requestedEvents.wheel = eventListeners.wheel;
755
- }
756
-
757
- if (!(events & CoreMouseEventType.UP)) {
758
- this._document!.removeEventListener('mouseup', requestedEvents.mouseup!);
759
- requestedEvents.mouseup = null;
760
- } else if (!requestedEvents.mouseup) {
761
- requestedEvents.mouseup = eventListeners.mouseup;
762
- }
763
-
764
- if (!(events & CoreMouseEventType.DRAG)) {
765
- this._document!.removeEventListener('mousemove', requestedEvents.mousedrag!);
766
- requestedEvents.mousedrag = null;
767
- } else if (!requestedEvents.mousedrag) {
768
- requestedEvents.mousedrag = eventListeners.mousedrag;
769
- }
770
- }));
771
- // force initial onProtocolChange so we dont miss early mouse requests
772
- this.coreMouseService.activeProtocol = this.coreMouseService.activeProtocol;
773
-
774
- /**
775
- * "Always on" event listeners.
776
- */
777
- this._register(addDisposableListener(el, 'mousedown', (ev: MouseEvent) => {
778
- ev.preventDefault();
779
- this.focus();
780
-
781
- // Don't send the mouse button to the pty if mouse events are disabled or
782
- // if the selection manager is having selection forced (ie. a modifier is
783
- // held).
784
- if (!this.coreMouseService.areMouseEventsActive || this._selectionService!.shouldForceSelection(ev)) {
785
- return;
786
- }
787
-
788
- sendEvent(ev);
789
-
790
- // Register additional global handlers which should keep reporting outside
791
- // of the terminal element.
792
- // Note: Other emulators also do this for 'mousedown' while a button
793
- // is held, we currently limit 'mousedown' to the terminal only.
794
- if (requestedEvents.mouseup) {
795
- this._document!.addEventListener('mouseup', requestedEvents.mouseup);
796
- }
797
- if (requestedEvents.mousedrag) {
798
- this._document!.addEventListener('mousemove', requestedEvents.mousedrag);
799
- }
800
-
801
- return this.cancel(ev);
802
- }));
803
-
804
- this._register(addDisposableListener(el, 'wheel', (ev: WheelEvent) => {
805
- // do nothing, if app side handles wheel itself
806
- if (requestedEvents.wheel) return;
807
-
808
- if (this._customWheelEventHandler && this._customWheelEventHandler(ev) === false) {
809
- return false;
810
- }
811
-
812
- if (!this.buffer.hasScrollback) {
813
- // Convert wheel events into up/down events when the buffer does not have scrollback, this
814
- // enables scrolling in apps hosted in the alt buffer such as vim or tmux even when mouse
815
- // events are not enabled.
816
- // This used implementation used get the actual lines/partial lines scrolled from the
817
- // viewport but since moving to the new viewport implementation has been simplified to
818
- // simply send a single up or down sequence.
819
-
820
- // Do nothing if there's no vertical scroll
821
- const deltaY = (ev as WheelEvent).deltaY;
822
- if (deltaY === 0) {
823
- return false;
824
- }
825
-
826
- const lines = self.coreMouseService.consumeWheelEvent(
827
- ev as WheelEvent,
828
- self._renderService?.dimensions?.device?.cell?.height,
829
- self._coreBrowserService?.dpr
830
- );
831
- if (lines === 0) {
832
- return this.cancel(ev, true);
833
- }
834
-
835
- // Construct and send sequences
836
- const sequence = C0.ESC + (this.coreService.decPrivateModes.applicationCursorKeys ? 'O' : '[') + (ev.deltaY < 0 ? 'A' : 'B');
837
- this.coreService.triggerDataEvent(sequence, true);
838
- return this.cancel(ev, true);
839
- }
840
- }, { passive: false }));
841
- }
842
-
843
-
844
671
  /**
845
672
  * Tells the renderer to refresh terminal content between two rows (inclusive) at the next
846
673
  * opportunity.
847
674
  * @param start The row to start from (between 0 and this.rows - 1).
848
675
  * @param end The row to end at (between start and this.rows - 1).
849
676
  */
850
- public refresh(start: number, end: number): void {
851
- this._renderService?.refreshRows(start, end);
677
+ public refresh(start: number, end: number, sync: boolean = false): void {
678
+ this._renderService?.refreshRows(start, end, sync);
852
679
  }
853
680
 
854
681
  /**
@@ -914,7 +741,7 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
914
741
  }
915
742
 
916
743
  public attachCustomWheelEventHandler(customWheelEventHandler: CustomWheelEventHandler): void {
917
- this._customWheelEventHandler = customWheelEventHandler;
744
+ this.mouseStateService.setCustomWheelEventHandler(customWheelEventHandler);
918
745
  }
919
746
 
920
747
  public registerLinkProvider(linkProvider: ILinkProvider): IDisposable {
@@ -1038,14 +865,16 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
1038
865
  this._unprocessedDeadKey = true;
1039
866
  }
1040
867
 
1041
- const result = evaluateKeyboardEvent(event, this.coreService.decPrivateModes.applicationCursorKeys, this.browser.isMac, this.options.macOptionIsMeta);
868
+ const result = this._keyboardService.evaluateKeyDown(event);
1042
869
 
1043
870
  this.updateCursorStyle(event);
1044
871
 
1045
872
  if (result.type === KeyboardResultType.PAGE_DOWN || result.type === KeyboardResultType.PAGE_UP) {
1046
873
  const scrollCount = this.rows - 1;
1047
874
  this.scrollLines(result.type === KeyboardResultType.PAGE_UP ? -scrollCount : scrollCount);
1048
- return this.cancel(event, true);
875
+ event.preventDefault();
876
+ event.stopPropagation();
877
+ return false;
1049
878
  }
1050
879
 
1051
880
  if (result.type === KeyboardResultType.SELECT_ALL) {
@@ -1058,7 +887,8 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
1058
887
 
1059
888
  if (result.cancel) {
1060
889
  // The event is canceled at the end already, is this necessary?
1061
- this.cancel(event, true);
890
+ event.preventDefault();
891
+ event.stopPropagation();
1062
892
  }
1063
893
 
1064
894
  if (!result.key) {
@@ -1066,8 +896,9 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
1066
896
  }
1067
897
 
1068
898
  // HACK: Process A-Z in the keypress event to fix an issue with macOS IMEs where lower case
1069
- // letters cannot be input while caps lock is on.
1070
- if (event.key && !event.ctrlKey && !event.altKey && !event.metaKey && event.key.length === 1) {
899
+ // letters cannot be input while caps lock is on. Skip this hack when using kitty protocol
900
+ // or Win32 input mode as they need to send proper sequences for all key events.
901
+ if (!this._keyboardService.useKitty && !this._keyboardService.useWin32InputMode && event.key && !event.ctrlKey && !event.altKey && !event.metaKey && event.key.length === 1) {
1071
902
  if (event.key.charCodeAt(0) >= 65 && event.key.charCodeAt(0) <= 90) {
1072
903
  return true;
1073
904
  }
@@ -1085,16 +916,19 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
1085
916
  this.textarea!.value = '';
1086
917
  }
1087
918
 
919
+ const wasModifierOnly = this._keyboardService.useWin32InputMode && wasModifierKeyOnlyEvent(event);
1088
920
  this._onKey.fire({ key: result.key, domEvent: event });
1089
921
  this._showCursor();
1090
- this.coreService.triggerDataEvent(result.key, true);
922
+ this.coreService.triggerDataEvent(result.key, !wasModifierOnly);
1091
923
 
1092
924
  // Cancel events when not in screen reader mode so events don't get bubbled up and handled by
1093
925
  // other listeners. When screen reader mode is enabled, we don't cancel them (unless ctrl or alt
1094
926
  // is also depressed) so that the cursor textarea can be updated, which triggers the screen
1095
927
  // reader to read it.
1096
928
  if (!this.optionsService.rawOptions.screenReaderMode || event.altKey || event.ctrlKey) {
1097
- return this.cancel(event, true);
929
+ event.preventDefault();
930
+ event.stopPropagation();
931
+ return false;
1098
932
  }
1099
933
 
1100
934
  this._keyDownHandled = true;
@@ -1125,6 +959,13 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
1125
959
  this.focus();
1126
960
  }
1127
961
 
962
+ // Handle key release for Kitty keyboard protocol
963
+ const result = this._keyboardService.evaluateKeyUp(ev);
964
+ if (result?.key) {
965
+ const wasModifierOnly = this._keyboardService.useWin32InputMode && wasModifierKeyOnlyEvent(ev);
966
+ this.coreService.triggerDataEvent(result.key, !wasModifierOnly);
967
+ }
968
+
1128
969
  this.updateCursorStyle(ev);
1129
970
  this._keyPressHandled = false;
1130
971
  }
@@ -1148,8 +989,6 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
1148
989
  return false;
1149
990
  }
1150
991
 
1151
- this.cancel(ev);
1152
-
1153
992
  if (ev.charCode) {
1154
993
  key = ev.charCode;
1155
994
  } else if (ev.which === null || ev.which === undefined) {
@@ -1202,8 +1041,6 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
1202
1041
 
1203
1042
  const text = ev.data;
1204
1043
  this.coreService.triggerDataEvent(text, true);
1205
-
1206
- this.cancel(ev);
1207
1044
  return true;
1208
1045
  }
1209
1046
 
@@ -1236,10 +1073,6 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
1236
1073
  * Clear the entire buffer, making the prompt line the new first line.
1237
1074
  */
1238
1075
  public clear(): void {
1239
- if (this.buffer.ybase === 0 && this.buffer.y === 0) {
1240
- // Don't clear if it's already clear
1241
- return;
1242
- }
1243
1076
  this.buffer.clearAllMarkers();
1244
1077
  this.buffer.lines.set(0, this.buffer.lines.get(this.buffer.ybase + this.buffer.y)!);
1245
1078
  this.buffer.lines.length = 1;
@@ -1274,6 +1107,7 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
1274
1107
 
1275
1108
  this._setup();
1276
1109
  super.reset();
1110
+ this._mouseService?.reset();
1277
1111
  this._selectionService?.reset();
1278
1112
  this._decorationService.reset();
1279
1113
 
@@ -1281,7 +1115,7 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
1281
1115
  this._customKeyEventHandler = customKeyEventHandler;
1282
1116
 
1283
1117
  // do a full screen refresh
1284
- this.refresh(0, this.rows - 1);
1118
+ this.refresh(0, this.rows - 1, true);
1285
1119
  }
1286
1120
 
1287
1121
  public clearTextureAtlas(): void {
@@ -1315,15 +1149,6 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
1315
1149
  }
1316
1150
  }
1317
1151
 
1318
- // TODO: Remove cancel function and cancelEvents option
1319
- public cancel(ev: MouseEvent | WheelEvent | KeyboardEvent | InputEvent, force?: boolean): boolean | undefined {
1320
- if (!this.options.cancelEvents && !force) {
1321
- return;
1322
- }
1323
- ev.preventDefault();
1324
- ev.stopPropagation();
1325
- return false;
1326
- }
1327
1152
  }
1328
1153
 
1329
1154
  /**
@@ -1333,5 +1158,10 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
1333
1158
  function wasModifierKeyOnlyEvent(ev: KeyboardEvent): boolean {
1334
1159
  return ev.keyCode === 16 || // Shift
1335
1160
  ev.keyCode === 17 || // Ctrl
1336
- ev.keyCode === 18; // Alt
1161
+ ev.keyCode === 18 || // Alt
1162
+ ev.keyCode === 91 || // Meta (Left)
1163
+ ev.keyCode === 92 || // Meta (Right)
1164
+ ev.keyCode === 93 || // Meta (Menu)
1165
+ ev.keyCode === 224 || // Meta (Firefox)
1166
+ ev.key === 'Meta';
1337
1167
  }