@xterm/xterm 6.1.0-beta.3 → 6.1.0-beta.300

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 +57 -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 -352
  12. package/src/browser/Dom.ts +178 -0
  13. package/src/browser/Linkifier.ts +14 -14
  14. package/src/browser/OscLinkProvider.ts +87 -19
  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 -22
  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 +62 -38
  64. package/src/common/Event.ts +118 -0
  65. package/src/common/InputHandler.ts +303 -104
  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 +9 -0
  73. package/src/common/WindowsMode.ts +2 -2
  74. package/src/common/buffer/AttributeData.ts +3 -2
  75. package/src/common/buffer/Buffer.ts +49 -34
  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 +5 -8
  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 -10
  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 -54
  116. package/src/common/services/UnicodeService.ts +6 -11
  117. package/typings/xterm.d.ts +333 -47
  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;
@@ -126,8 +128,6 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
126
128
  public readonly onCursorMove = this._onCursorMove.event;
127
129
  private readonly _onKey = this._register(new Emitter<{ key: string, domEvent: KeyboardEvent }>());
128
130
  public readonly onKey = this._onKey.event;
129
- private readonly _onRender = this._register(new Emitter<{ start: number, end: number }>());
130
- public readonly onRender = this._onRender.event;
131
131
  private readonly _onSelectionChange = this._register(new Emitter<void>());
132
132
  public readonly onSelectionChange = this._onSelectionChange.event;
133
133
  private readonly _onTitleChange = this._register(new Emitter<string>());
@@ -136,15 +136,35 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
136
136
  public readonly onBell = this._onBell.event;
137
137
 
138
138
  private _onFocus = this._register(new Emitter<void>());
139
- public get onFocus(): Event<void> { return this._onFocus.event; }
139
+ public get onFocus(): IEvent<void> { return this._onFocus.event; }
140
140
  private _onBlur = this._register(new Emitter<void>());
141
- public get onBlur(): Event<void> { return this._onBlur.event; }
141
+ public get onBlur(): IEvent<void> { return this._onBlur.event; }
142
142
  private _onA11yCharEmitter = this._register(new Emitter<string>());
143
- public get onA11yChar(): Event<string> { return this._onA11yCharEmitter.event; }
143
+ public get onA11yChar(): IEvent<string> { return this._onA11yCharEmitter.event; }
144
144
  private _onA11yTabEmitter = this._register(new Emitter<number>());
145
- public get onA11yTab(): Event<number> { return this._onA11yTabEmitter.event; }
145
+ public get onA11yTab(): IEvent<number> { return this._onA11yTabEmitter.event; }
146
146
  private _onWillOpen = this._register(new Emitter<HTMLElement>());
147
- 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
+ }
148
168
 
149
169
  constructor(
150
170
  options: Partial<ITerminalOptions> = {}
@@ -155,6 +175,8 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
155
175
 
156
176
  this._decorationService = this._instantiationService.createInstance(DecorationService);
157
177
  this._instantiationService.setService(IDecorationService, this._decorationService);
178
+ this._keyboardService = this._instantiationService.createInstance(KeyboardService);
179
+ this._instantiationService.setService(IKeyboardService, this._keyboardService);
158
180
  this._linkProviderService = this._instantiationService.createInstance(LinkProviderService);
159
181
  this._instantiationService.setService(ILinkProviderService, this._linkProviderService);
160
182
  this._linkProviderService.registerLinkProvider(this._instantiationService.createInstance(OscLinkProvider));
@@ -166,10 +188,10 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
166
188
  this._register(this._inputHandler.onRequestReset(() => this.reset()));
167
189
  this._register(this._inputHandler.onRequestWindowsOptionsReport(type => this._reportWindowsOptions(type)));
168
190
  this._register(this._inputHandler.onColor((event) => this._handleColorEvent(event)));
169
- this._register(Event.forward(this._inputHandler.onCursorMove, this._onCursorMove));
170
- this._register(Event.forward(this._inputHandler.onTitleChange, this._onTitleChange));
171
- this._register(Event.forward(this._inputHandler.onA11yChar, this._onA11yCharEmitter));
172
- 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));
173
195
 
174
196
  // Setup listeners
175
197
  this._register(this._bufferService.onResize(e => this._afterResize(e.cols, e.rows)));
@@ -190,7 +212,7 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
190
212
  if (!this._themeService) return;
191
213
  for (const req of event) {
192
214
  let acc: 'foreground' | 'background' | 'cursor' | 'ansi';
193
- let ident = '';
215
+ let ident: string;
194
216
  switch (req.index) {
195
217
  case SpecialColorIndex.FOREGROUND: // OSC 10 | 110
196
218
  acc = 'foreground';
@@ -214,7 +236,7 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
214
236
  const colorRgb = color.toColorRGB(acc === 'ansi'
215
237
  ? this._themeService.colors.ansi[req.index]
216
238
  : this._themeService.colors[acc]);
217
- this.coreService.triggerDataEvent(`${C0.ESC}]${ident};${toRgbString(colorRgb)}${C1_ESCAPED.ST}`);
239
+ this.coreService.triggerDataEvent(`${C0.ESC}]${ident};${toRgbString(colorRgb)}${C1ESCAPED.ST}`);
218
240
  break;
219
241
  case ColorRequestType.SET:
220
242
  if (acc === 'ansi') {
@@ -231,6 +253,20 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
231
253
  }
232
254
  }
233
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
+
234
270
  protected _setup(): void {
235
271
  super._setup();
236
272
 
@@ -378,7 +414,16 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
378
414
  this._register(addDisposableListener(this.textarea!, 'keyup', (ev: KeyboardEvent) => this._keyUp(ev), true));
379
415
  this._register(addDisposableListener(this.textarea!, 'keydown', (ev: KeyboardEvent) => this._keyDown(ev), true));
380
416
  this._register(addDisposableListener(this.textarea!, 'keypress', (ev: KeyboardEvent) => this._keyPress(ev), true));
381
- 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
+ }));
382
427
  this._register(addDisposableListener(this.textarea!, 'compositionupdate', (e: CompositionEvent) => this._compositionHelper!.compositionupdate(e)));
383
428
  this._register(addDisposableListener(this.textarea!, 'compositionend', () => this._compositionHelper!.compositionend()));
384
429
  this._register(addDisposableListener(this.textarea!, 'input', (ev: InputEvent) => this._inputEvent(ev), true));
@@ -418,6 +463,8 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
418
463
  this.element.dir = 'ltr'; // xterm.css assumes LTR
419
464
  this.element.classList.add('terminal');
420
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)));
421
468
  parent.appendChild(this.element);
422
469
 
423
470
  // Performance: Use a document fragment to build the terminal
@@ -445,6 +492,7 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
445
492
  // https://issuetracker.google.com/issues/260170397
446
493
  this.textarea.setAttribute('aria-multiline', 'false');
447
494
  }
495
+ this.textarea.setAttribute('autocomplete', 'off');
448
496
  this.textarea.setAttribute('autocorrect', 'off');
449
497
  this.textarea.setAttribute('autocapitalize', 'off');
450
498
  this.textarea.setAttribute('spellcheck', 'false');
@@ -458,7 +506,7 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
458
506
  this.textarea,
459
507
  parent.ownerDocument.defaultView ?? window,
460
508
  // Force unsafe null in node.js environment for tests
461
- this._document ?? (typeof window !== 'undefined') ? window.document : null as any
509
+ this._document ?? ((typeof window !== 'undefined') ? window.document : null as any)
462
510
  ));
463
511
  this._instantiationService.setService(ICoreBrowserService, this._coreBrowserService);
464
512
 
@@ -472,12 +520,33 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
472
520
  this._themeService = this._instantiationService.createInstance(ThemeService);
473
521
  this._instantiationService.setService(IThemeService, this._themeService);
474
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
+
475
533
  this._characterJoinerService = this._instantiationService.createInstance(CharacterJoinerService);
476
534
  this._instantiationService.setService(ICharacterJoinerService, this._characterJoinerService);
477
535
 
478
536
  this._renderService = this._register(this._instantiationService.createInstance(RenderService, this.rows, this.screenElement));
479
537
  this._instantiationService.setService(IRenderService, this._renderService);
480
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
+ })));
481
550
  this.onResize(e => this._renderService!.resize(e.cols, e.rows));
482
551
 
483
552
  this._compositionView = this._document.createElement('div');
@@ -485,8 +554,8 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
485
554
  this._compositionHelper = this._instantiationService.createInstance(CompositionHelper, this.textarea, this._compositionView);
486
555
  this._helperContainer.appendChild(this._compositionView);
487
556
 
488
- this._mouseService = this._instantiationService.createInstance(MouseService);
489
- this._instantiationService.setService(IMouseService, this._mouseService);
557
+ this._mouseCoordsService = this._instantiationService.createInstance(MouseCoordsService);
558
+ this._instantiationService.setService(IMouseCoordsService, this._mouseCoordsService);
490
559
 
491
560
  const linkifier = this._linkifier.value = this._register(this._instantiationService.createInstance(Linkifier, this.screenElement));
492
561
 
@@ -495,8 +564,9 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
495
564
 
496
565
  try {
497
566
  this._onWillOpen.fire(this.element);
567
+ } catch (e) {
568
+ this._logService.error('onWillOpen handler threw an exception', e);
498
569
  }
499
- catch { /* fails to load addon for some reason */ }
500
570
  if (!this._renderService.hasRenderer()) {
501
571
  this._renderService.setRenderer(this._createRenderer());
502
572
  }
@@ -505,7 +575,10 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
505
575
  this._renderService!.handleCursorMove();
506
576
  this._syncTextArea();
507
577
  }));
508
- 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
+ }));
509
582
  this._register(this.onBlur(() => this._renderService!.handleBlur()));
510
583
  this._register(this.onFocus(() => this._renderService!.handleFocus()));
511
584
 
@@ -521,6 +594,8 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
521
594
  linkifier
522
595
  ));
523
596
  this._instantiationService.setService(ISelectionService, this._selectionService);
597
+ this._mouseService = this._instantiationService.createInstance(MouseService);
598
+ this._instantiationService.setService(IMouseService, this._mouseService);
524
599
  this._register(this._selectionService.onRequestScrollLines(e => this.scrollLines(e.amount, e.suppressScrollEvent)));
525
600
  this._register(this._selectionService.onSelectionChange(() => this._onSelectionChange.fire()));
526
601
  this._register(this._selectionService.onRequestRedraw(e => this._renderService!.handleSelectionChanged(e.start, e.end, e.columnSelectMode)));
@@ -532,7 +607,7 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
532
607
  this.textarea!.focus();
533
608
  this.textarea!.select();
534
609
  }));
535
- this._register(Event.any(
610
+ this._register(EventUtils.any(
536
611
  this._onScroll.event,
537
612
  this._inputHandler.onScroll
538
613
  )(() => {
@@ -544,11 +619,12 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
544
619
  this._register(addDisposableListener(this.element, 'mousedown', (e: MouseEvent) => this._selectionService!.handleMouseDown(e)));
545
620
 
546
621
  // apply mouse event classes set by escape codes before terminal was attached
547
- if (this.coreMouseService.areMouseEventsActive) {
622
+ if (this.mouseStateService.areMouseEventsActive && !this.options.mouseEventsRequireAlt) {
548
623
  this._selectionService.disable();
549
- this.element.classList.add('enable-mouse-events');
624
+ this.element.classList.add(MouseEventCssClasses.ENABLE_MOUSE_EVENTS);
550
625
  } else {
551
626
  this._selectionService.enable();
627
+ this.element.classList.remove(MouseEventCssClasses.ENABLE_MOUSE_EVENTS);
552
628
  }
553
629
 
554
630
  if (this.options.screenReaderMode) {
@@ -558,11 +634,14 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
558
634
  }
559
635
  this._register(this.optionsService.onSpecificOptionChange('screenReaderMode', e => this._handleScreenReaderModeOptionChange(e)));
560
636
 
561
- if (this.options.overviewRuler.width) {
637
+ const showScrollbar = this.options.scrollbar?.showScrollbar ?? true;
638
+ const overviewRulerWidth = this.options.scrollbar?.width;
639
+ if (showScrollbar && overviewRulerWidth) {
562
640
  this._overviewRulerRenderer = this._register(this._instantiationService.createInstance(OverviewRulerRenderer, this._viewportElement, this.screenElement));
563
641
  }
564
- this.optionsService.onSpecificOptionChange('overviewRuler', value => {
565
- 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) {
566
645
  this._overviewRulerRenderer = this._register(this._instantiationService.createInstance(OverviewRulerRenderer, this._viewportElement, this.screenElement));
567
646
  }
568
647
  });
@@ -577,280 +656,26 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
577
656
 
578
657
  // Listen for mouse events and translate
579
658
  // them into terminal mouse protocols.
580
- 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());
581
665
  }
582
666
 
583
667
  private _createRenderer(): IRenderer {
584
668
  return this._instantiationService.createInstance(DomRenderer, this, this._document!, this.element!, this.screenElement!, this._viewportElement!, this._helperContainer!, this.linkifier!);
585
669
  }
586
670
 
587
- /**
588
- * Bind certain mouse events to the terminal.
589
- * By default only 3 button + wheel up/down is ativated. For higher buttons
590
- * no mouse report will be created. Typically the standard actions will be active.
591
- *
592
- * There are several reasons not to enable support for higher buttons/wheel:
593
- * - Button 4 and 5 are typically used for history back and forward navigation,
594
- * there is no straight forward way to supress/intercept those standard actions.
595
- * - Support for higher buttons does not work in some platform/browser combinations.
596
- * - Left/right wheel was not tested.
597
- * - Emulators vary in mouse button support, typically only 3 buttons and
598
- * wheel up/down work reliable.
599
- *
600
- * TODO: Move mouse event code into its own file.
601
- */
602
- public bindMouse(): void {
603
- const self = this;
604
- const el = this.element!;
605
-
606
- // send event to CoreMouseService
607
- function sendEvent(ev: MouseEvent | WheelEvent): boolean {
608
- // get mouse coordinates
609
- const pos = self._mouseService!.getMouseReportCoords(ev, self.screenElement!);
610
- if (!pos) {
611
- return false;
612
- }
613
-
614
- let but: CoreMouseButton;
615
- let action: CoreMouseAction | undefined;
616
- switch ((ev as any).overrideType || ev.type) {
617
- case 'mousemove':
618
- action = CoreMouseAction.MOVE;
619
- if (ev.buttons === undefined) {
620
- // buttons is not supported on macOS, try to get a value from button instead
621
- but = CoreMouseButton.NONE;
622
- if (ev.button !== undefined) {
623
- but = ev.button < 3 ? ev.button : CoreMouseButton.NONE;
624
- }
625
- } else {
626
- // according to MDN buttons only reports up to button 5 (AUX2)
627
- but = ev.buttons & 1 ? CoreMouseButton.LEFT :
628
- ev.buttons & 4 ? CoreMouseButton.MIDDLE :
629
- ev.buttons & 2 ? CoreMouseButton.RIGHT :
630
- CoreMouseButton.NONE; // fallback to NONE
631
- }
632
- break;
633
- case 'mouseup':
634
- action = CoreMouseAction.UP;
635
- but = ev.button < 3 ? ev.button : CoreMouseButton.NONE;
636
- break;
637
- case 'mousedown':
638
- action = CoreMouseAction.DOWN;
639
- but = ev.button < 3 ? ev.button : CoreMouseButton.NONE;
640
- break;
641
- case 'wheel':
642
- if (self._customWheelEventHandler && self._customWheelEventHandler(ev as WheelEvent) === false) {
643
- return false;
644
- }
645
- const deltaY = (ev as WheelEvent).deltaY;
646
- if (deltaY === 0) {
647
- return false;
648
- }
649
- const lines = self.coreMouseService.consumeWheelEvent(
650
- ev as WheelEvent,
651
- self._renderService?.dimensions?.device?.cell?.height,
652
- self._coreBrowserService?.dpr
653
- );
654
- if (lines === 0) {
655
- return false;
656
- }
657
- action = deltaY < 0 ? CoreMouseAction.UP : CoreMouseAction.DOWN;
658
- but = CoreMouseButton.WHEEL;
659
- break;
660
- default:
661
- // dont handle other event types by accident
662
- return false;
663
- }
664
-
665
- // exit if we cannot determine valid button/action values
666
- // do nothing for higher buttons than wheel
667
- if (action === undefined || but === undefined || but > CoreMouseButton.WHEEL) {
668
- return false;
669
- }
670
-
671
- return self.coreMouseService.triggerMouseEvent({
672
- col: pos.col,
673
- row: pos.row,
674
- x: pos.x,
675
- y: pos.y,
676
- button: but,
677
- action,
678
- ctrl: ev.ctrlKey,
679
- alt: ev.altKey,
680
- shift: ev.shiftKey
681
- });
682
- }
683
-
684
- /**
685
- * Event listener state handling.
686
- * We listen to the onProtocolChange event of CoreMouseService and put
687
- * requested listeners in `requestedEvents`. With this the listeners
688
- * have all bits to do the event listener juggling.
689
- * Note: 'mousedown' currently is "always on" and not managed
690
- * by onProtocolChange.
691
- */
692
- const requestedEvents: { [key: string]: ((ev: MouseEvent | WheelEvent) => void) | null } = {
693
- mouseup: null,
694
- wheel: null,
695
- mousedrag: null,
696
- mousemove: null
697
- };
698
- const eventListeners: { [key: string]: (ev: any) => void | boolean } = {
699
- mouseup: (ev: MouseEvent) => {
700
- sendEvent(ev);
701
- if (!ev.buttons) {
702
- // if no other button is held remove global handlers
703
- this._document!.removeEventListener('mouseup', requestedEvents.mouseup!);
704
- if (requestedEvents.mousedrag) {
705
- this._document!.removeEventListener('mousemove', requestedEvents.mousedrag);
706
- }
707
- }
708
- return this.cancel(ev);
709
- },
710
- wheel: (ev: WheelEvent) => {
711
- sendEvent(ev);
712
- return this.cancel(ev, true);
713
- },
714
- mousedrag: (ev: MouseEvent) => {
715
- // deal only with move while a button is held
716
- if (ev.buttons) {
717
- sendEvent(ev);
718
- }
719
- },
720
- mousemove: (ev: MouseEvent) => {
721
- // deal only with move without any button
722
- if (!ev.buttons) {
723
- sendEvent(ev);
724
- }
725
- }
726
- };
727
- this._register(this.coreMouseService.onProtocolChange(events => {
728
- // apply global changes on events
729
- if (events) {
730
- if (this.optionsService.rawOptions.logLevel === 'debug') {
731
- this._logService.debug('Binding to mouse events:', this.coreMouseService.explainEvents(events));
732
- }
733
- this.element!.classList.add('enable-mouse-events');
734
- this._selectionService!.disable();
735
- } else {
736
- this._logService.debug('Unbinding from mouse events.');
737
- this.element!.classList.remove('enable-mouse-events');
738
- this._selectionService!.enable();
739
- }
740
-
741
- // add/remove handlers from requestedEvents
742
-
743
- if (!(events & CoreMouseEventType.MOVE)) {
744
- el.removeEventListener('mousemove', requestedEvents.mousemove!);
745
- requestedEvents.mousemove = null;
746
- } else if (!requestedEvents.mousemove) {
747
- el.addEventListener('mousemove', eventListeners.mousemove);
748
- requestedEvents.mousemove = eventListeners.mousemove;
749
- }
750
-
751
- if (!(events & CoreMouseEventType.WHEEL)) {
752
- el.removeEventListener('wheel', requestedEvents.wheel!);
753
- requestedEvents.wheel = null;
754
- } else if (!requestedEvents.wheel) {
755
- el.addEventListener('wheel', eventListeners.wheel, { passive: false });
756
- requestedEvents.wheel = eventListeners.wheel;
757
- }
758
-
759
- if (!(events & CoreMouseEventType.UP)) {
760
- this._document!.removeEventListener('mouseup', requestedEvents.mouseup!);
761
- requestedEvents.mouseup = null;
762
- } else if (!requestedEvents.mouseup) {
763
- requestedEvents.mouseup = eventListeners.mouseup;
764
- }
765
-
766
- if (!(events & CoreMouseEventType.DRAG)) {
767
- this._document!.removeEventListener('mousemove', requestedEvents.mousedrag!);
768
- requestedEvents.mousedrag = null;
769
- } else if (!requestedEvents.mousedrag) {
770
- requestedEvents.mousedrag = eventListeners.mousedrag;
771
- }
772
- }));
773
- // force initial onProtocolChange so we dont miss early mouse requests
774
- this.coreMouseService.activeProtocol = this.coreMouseService.activeProtocol;
775
-
776
- /**
777
- * "Always on" event listeners.
778
- */
779
- this._register(addDisposableListener(el, 'mousedown', (ev: MouseEvent) => {
780
- ev.preventDefault();
781
- this.focus();
782
-
783
- // Don't send the mouse button to the pty if mouse events are disabled or
784
- // if the selection manager is having selection forced (ie. a modifier is
785
- // held).
786
- if (!this.coreMouseService.areMouseEventsActive || this._selectionService!.shouldForceSelection(ev)) {
787
- return;
788
- }
789
-
790
- sendEvent(ev);
791
-
792
- // Register additional global handlers which should keep reporting outside
793
- // of the terminal element.
794
- // Note: Other emulators also do this for 'mousedown' while a button
795
- // is held, we currently limit 'mousedown' to the terminal only.
796
- if (requestedEvents.mouseup) {
797
- this._document!.addEventListener('mouseup', requestedEvents.mouseup);
798
- }
799
- if (requestedEvents.mousedrag) {
800
- this._document!.addEventListener('mousemove', requestedEvents.mousedrag);
801
- }
802
-
803
- return this.cancel(ev);
804
- }));
805
-
806
- this._register(addDisposableListener(el, 'wheel', (ev: WheelEvent) => {
807
- // do nothing, if app side handles wheel itself
808
- if (requestedEvents.wheel) return;
809
-
810
- if (this._customWheelEventHandler && this._customWheelEventHandler(ev) === false) {
811
- return false;
812
- }
813
-
814
- if (!this.buffer.hasScrollback) {
815
- // Convert wheel events into up/down events when the buffer does not have scrollback, this
816
- // enables scrolling in apps hosted in the alt buffer such as vim or tmux even when mouse
817
- // events are not enabled.
818
- // This used implementation used get the actual lines/partial lines scrolled from the
819
- // viewport but since moving to the new viewport implementation has been simplified to
820
- // simply send a single up or down sequence.
821
-
822
- // Do nothing if there's no vertical scroll
823
- const deltaY = (ev as WheelEvent).deltaY;
824
- if (deltaY === 0) {
825
- return false;
826
- }
827
-
828
- const lines = self.coreMouseService.consumeWheelEvent(
829
- ev as WheelEvent,
830
- self._renderService?.dimensions?.device?.cell?.height,
831
- self._coreBrowserService?.dpr
832
- );
833
- if (lines === 0) {
834
- return this.cancel(ev, true);
835
- }
836
-
837
- // Construct and send sequences
838
- const sequence = C0.ESC + (this.coreService.decPrivateModes.applicationCursorKeys ? 'O' : '[') + (ev.deltaY < 0 ? 'A' : 'B');
839
- this.coreService.triggerDataEvent(sequence, true);
840
- return this.cancel(ev, true);
841
- }
842
- }, { passive: false }));
843
- }
844
-
845
-
846
671
  /**
847
672
  * Tells the renderer to refresh terminal content between two rows (inclusive) at the next
848
673
  * opportunity.
849
674
  * @param start The row to start from (between 0 and this.rows - 1).
850
675
  * @param end The row to end at (between start and this.rows - 1).
851
676
  */
852
- public refresh(start: number, end: number): void {
853
- this._renderService?.refreshRows(start, end);
677
+ public refresh(start: number, end: number, sync: boolean = false): void {
678
+ this._renderService?.refreshRows(start, end, sync);
854
679
  }
855
680
 
856
681
  /**
@@ -916,7 +741,7 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
916
741
  }
917
742
 
918
743
  public attachCustomWheelEventHandler(customWheelEventHandler: CustomWheelEventHandler): void {
919
- this._customWheelEventHandler = customWheelEventHandler;
744
+ this.mouseStateService.setCustomWheelEventHandler(customWheelEventHandler);
920
745
  }
921
746
 
922
747
  public registerLinkProvider(linkProvider: ILinkProvider): IDisposable {
@@ -1040,14 +865,16 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
1040
865
  this._unprocessedDeadKey = true;
1041
866
  }
1042
867
 
1043
- const result = evaluateKeyboardEvent(event, this.coreService.decPrivateModes.applicationCursorKeys, this.browser.isMac, this.options.macOptionIsMeta);
868
+ const result = this._keyboardService.evaluateKeyDown(event);
1044
869
 
1045
870
  this.updateCursorStyle(event);
1046
871
 
1047
872
  if (result.type === KeyboardResultType.PAGE_DOWN || result.type === KeyboardResultType.PAGE_UP) {
1048
873
  const scrollCount = this.rows - 1;
1049
874
  this.scrollLines(result.type === KeyboardResultType.PAGE_UP ? -scrollCount : scrollCount);
1050
- return this.cancel(event, true);
875
+ event.preventDefault();
876
+ event.stopPropagation();
877
+ return false;
1051
878
  }
1052
879
 
1053
880
  if (result.type === KeyboardResultType.SELECT_ALL) {
@@ -1060,7 +887,8 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
1060
887
 
1061
888
  if (result.cancel) {
1062
889
  // The event is canceled at the end already, is this necessary?
1063
- this.cancel(event, true);
890
+ event.preventDefault();
891
+ event.stopPropagation();
1064
892
  }
1065
893
 
1066
894
  if (!result.key) {
@@ -1068,8 +896,9 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
1068
896
  }
1069
897
 
1070
898
  // HACK: Process A-Z in the keypress event to fix an issue with macOS IMEs where lower case
1071
- // letters cannot be input while caps lock is on.
1072
- 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) {
1073
902
  if (event.key.charCodeAt(0) >= 65 && event.key.charCodeAt(0) <= 90) {
1074
903
  return true;
1075
904
  }
@@ -1087,16 +916,19 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
1087
916
  this.textarea!.value = '';
1088
917
  }
1089
918
 
919
+ const wasModifierOnly = this._keyboardService.useWin32InputMode && wasModifierKeyOnlyEvent(event);
1090
920
  this._onKey.fire({ key: result.key, domEvent: event });
1091
921
  this._showCursor();
1092
- this.coreService.triggerDataEvent(result.key, true);
922
+ this.coreService.triggerDataEvent(result.key, !wasModifierOnly);
1093
923
 
1094
924
  // Cancel events when not in screen reader mode so events don't get bubbled up and handled by
1095
925
  // other listeners. When screen reader mode is enabled, we don't cancel them (unless ctrl or alt
1096
926
  // is also depressed) so that the cursor textarea can be updated, which triggers the screen
1097
927
  // reader to read it.
1098
928
  if (!this.optionsService.rawOptions.screenReaderMode || event.altKey || event.ctrlKey) {
1099
- return this.cancel(event, true);
929
+ event.preventDefault();
930
+ event.stopPropagation();
931
+ return false;
1100
932
  }
1101
933
 
1102
934
  this._keyDownHandled = true;
@@ -1127,6 +959,13 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
1127
959
  this.focus();
1128
960
  }
1129
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
+
1130
969
  this.updateCursorStyle(ev);
1131
970
  this._keyPressHandled = false;
1132
971
  }
@@ -1150,8 +989,6 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
1150
989
  return false;
1151
990
  }
1152
991
 
1153
- this.cancel(ev);
1154
-
1155
992
  if (ev.charCode) {
1156
993
  key = ev.charCode;
1157
994
  } else if (ev.which === null || ev.which === undefined) {
@@ -1204,8 +1041,6 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
1204
1041
 
1205
1042
  const text = ev.data;
1206
1043
  this.coreService.triggerDataEvent(text, true);
1207
-
1208
- this.cancel(ev);
1209
1044
  return true;
1210
1045
  }
1211
1046
 
@@ -1238,10 +1073,6 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
1238
1073
  * Clear the entire buffer, making the prompt line the new first line.
1239
1074
  */
1240
1075
  public clear(): void {
1241
- if (this.buffer.ybase === 0 && this.buffer.y === 0) {
1242
- // Don't clear if it's already clear
1243
- return;
1244
- }
1245
1076
  this.buffer.clearAllMarkers();
1246
1077
  this.buffer.lines.set(0, this.buffer.lines.get(this.buffer.ybase + this.buffer.y)!);
1247
1078
  this.buffer.lines.length = 1;
@@ -1276,6 +1107,7 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
1276
1107
 
1277
1108
  this._setup();
1278
1109
  super.reset();
1110
+ this._mouseService?.reset();
1279
1111
  this._selectionService?.reset();
1280
1112
  this._decorationService.reset();
1281
1113
 
@@ -1283,7 +1115,7 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
1283
1115
  this._customKeyEventHandler = customKeyEventHandler;
1284
1116
 
1285
1117
  // do a full screen refresh
1286
- this.refresh(0, this.rows - 1);
1118
+ this.refresh(0, this.rows - 1, true);
1287
1119
  }
1288
1120
 
1289
1121
  public clearTextureAtlas(): void {
@@ -1317,15 +1149,6 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
1317
1149
  }
1318
1150
  }
1319
1151
 
1320
- // TODO: Remove cancel function and cancelEvents option
1321
- public cancel(ev: MouseEvent | WheelEvent | KeyboardEvent | InputEvent, force?: boolean): boolean | undefined {
1322
- if (!this.options.cancelEvents && !force) {
1323
- return;
1324
- }
1325
- ev.preventDefault();
1326
- ev.stopPropagation();
1327
- return false;
1328
- }
1329
1152
  }
1330
1153
 
1331
1154
  /**
@@ -1335,5 +1158,10 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
1335
1158
  function wasModifierKeyOnlyEvent(ev: KeyboardEvent): boolean {
1336
1159
  return ev.keyCode === 16 || // Shift
1337
1160
  ev.keyCode === 17 || // Ctrl
1338
- 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';
1339
1167
  }