monaco-editor 0.56.0-dev-20260119 → 0.56.0-dev-20260121
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.
- package/dev/vs/basic-languages/monaco.contribution.js +18 -18
- package/dev/vs/{cssMode-VP5J4n2d.js → cssMode-B0VkNrib.js} +1 -1
- package/dev/vs/editor/editor.main.css +42 -25
- package/dev/vs/editor/editor.main.js +1 -1
- package/dev/vs/{editor-ML6zs6Go.js → editor-CR18QzPP.js} +633 -162
- package/dev/vs/editor.js +1 -1
- package/dev/vs/{freemarker2-DOuHb9T9.js → freemarker2-Byr9HmH9.js} +1 -1
- package/dev/vs/{handlebars-CEHZxVsE.js → handlebars-BEVXeROF.js} +1 -1
- package/dev/vs/{html-CHMe_cBk.js → html-CetHjWIf.js} +1 -1
- package/dev/vs/{htmlMode-D7MQf6Yp.js → htmlMode-BNKYUVNo.js} +1 -1
- package/dev/vs/{index-KO0Jv4kb.js → index-g_7JbDIY.js} +1 -1
- package/dev/vs/index.js +1 -1
- package/dev/vs/{javascript-hfXEMgFg.js → javascript-BEgEU725.js} +1 -1
- package/dev/vs/{jsonMode-Dp9qexJG.js → jsonMode-CT2UkfFE.js} +1 -1
- package/dev/vs/language/css/monaco.contribution.js +1 -1
- package/dev/vs/language/html/monaco.contribution.js +1 -1
- package/dev/vs/language/json/monaco.contribution.js +1 -1
- package/dev/vs/language/typescript/monaco.contribution.js +1 -1
- package/dev/vs/{liquid-C5xy2cvN.js → liquid-D-aiCb1P.js} +1 -1
- package/dev/vs/{lspLanguageFeatures-D6ykJL1B.js → lspLanguageFeatures-CE9Occyu.js} +1 -1
- package/dev/vs/{mdx-DTsW_-Y_.js → mdx-DchJ8pbq.js} +1 -1
- package/dev/vs/{monaco.contribution-DuzmV_VZ.js → monaco.contribution-CHqb1dWh.js} +2 -2
- package/dev/vs/{monaco.contribution-t7Hz4wVA.js → monaco.contribution-CVBrIlxn.js} +2 -2
- package/dev/vs/{monaco.contribution-CcoogmES.js → monaco.contribution-CZxuzvA9.js} +2 -2
- package/dev/vs/{monaco.contribution-CQ8dNY-Q.js → monaco.contribution-Cw4OdERZ.js} +2 -2
- package/dev/vs/nls/lang/cs.js +1 -1
- package/dev/vs/nls/lang/de.js +1 -1
- package/dev/vs/nls/lang/es.js +1 -1
- package/dev/vs/nls/lang/fr.js +1 -1
- package/dev/vs/nls/lang/it.js +1 -1
- package/dev/vs/nls/lang/ja.js +1 -1
- package/dev/vs/nls/lang/ko.js +1 -1
- package/dev/vs/nls/lang/pl.js +1 -1
- package/dev/vs/nls/lang/pt-br.js +1 -1
- package/dev/vs/nls/lang/ru.js +1 -1
- package/dev/vs/nls/lang/tr.js +1 -1
- package/dev/vs/nls/lang/zh-cn.js +1 -1
- package/dev/vs/nls/lang/zh-tw.js +1 -1
- package/dev/vs/{python-1ZtmJ8bh.js → python-BCOSaCC8.js} +1 -1
- package/dev/vs/{razor-D7Pdon_S.js → razor-BM2tZCwj.js} +1 -1
- package/dev/vs/{toggleHighContrast-Btd2ryZF.js → toggleHighContrast-CLgtrrIB.js} +148 -315
- package/dev/vs/{tsMode-Dy3ckMs8.js → tsMode-jpkv3SbL.js} +1 -1
- package/dev/vs/{typescript-BBL8N09V.js → typescript-f8pt88eA.js} +1 -1
- package/dev/vs/{workers-B9Ao1ciR.js → workers-zrUx_2Gw.js} +1 -1
- package/dev/vs/{xml-7BH7GgP4.js → xml-CmSjtiR0.js} +1 -1
- package/dev/vs/{yaml-DvwGvgS8.js → yaml-PRriLGdw.js} +1 -1
- package/esm/vs/base/browser/markdownRenderer.js +1 -0
- package/esm/vs/base/browser/ui/actionbar/actionViewItems.js +4 -1
- package/esm/vs/base/browser/ui/actionbar/actionbar.css +8 -5
- package/esm/vs/base/browser/ui/contextview/contextview.js +1 -1
- package/esm/vs/base/browser/ui/list/list.js +2 -1
- package/esm/vs/base/browser/ui/list/listWidget.js +62 -5
- package/esm/vs/base/browser/ui/tree/abstractTree.js +4 -1
- package/esm/vs/base/browser/ui/tree/asyncDataTree.js +4 -1
- package/esm/vs/editor/browser/controller/editContext/clipboardUtils.js +81 -35
- package/esm/vs/editor/browser/controller/editContext/editContext.js +11 -0
- package/esm/vs/editor/browser/controller/editContext/native/nativeEditContext.js +38 -18
- package/esm/vs/editor/browser/controller/editContext/textArea/textAreaEditContext.js +4 -0
- package/esm/vs/editor/browser/controller/editContext/textArea/textAreaEditContextInput.js +39 -16
- package/esm/vs/editor/browser/dataTransfer.js +1 -1
- package/esm/vs/editor/browser/view.js +21 -1
- package/esm/vs/editor/browser/widget/codeEditor/codeEditorWidget.js +18 -0
- package/esm/vs/editor/common/model/bracketPairsTextModelPart/colorizedBracketPairsDecorationProvider.js +3 -3
- package/esm/vs/editor/common/model/textModel.js +7 -5
- package/esm/vs/editor/common/model/tokens/tokenizationFontDecorationsProvider.js +21 -17
- package/esm/vs/editor/common/viewModel/viewModelDecorations.js +11 -4
- package/esm/vs/editor/common/viewModel/viewModelImpl.js +25 -14
- package/esm/vs/editor/contrib/clipboard/browser/clipboard.js +3 -3
- package/esm/vs/editor/contrib/dropOrPasteInto/browser/copyPasteController.js +28 -64
- package/esm/vs/editor/contrib/floatingMenu/browser/floatingMenu.css +27 -20
- package/esm/vs/editor/contrib/floatingMenu/browser/floatingMenu.js +37 -9
- package/esm/vs/editor/contrib/inlineCompletions/browser/model/inlineCompletionsModel.js +2 -2
- package/esm/vs/editor/contrib/inlineCompletions/browser/view/ghostText/ghostTextView.css +7 -0
- package/esm/vs/editor/contrib/inlineCompletions/browser/view/ghostText/ghostTextView.js +22 -3
- package/esm/vs/editor/contrib/inlineCompletions/browser/view/inlineEdits/components/gutterIndicatorView.js +20 -14
- package/esm/vs/editor/contrib/inlineCompletions/browser/view/inlineSuggestionsView.js +1 -0
- package/esm/vs/editor/editor.api.d.ts +5 -1
- package/esm/vs/nls/lang/cs.js +1 -1
- package/esm/vs/nls/lang/de.js +1 -1
- package/esm/vs/nls/lang/es.js +1 -1
- package/esm/vs/nls/lang/fr.js +1 -1
- package/esm/vs/nls/lang/it.js +1 -1
- package/esm/vs/nls/lang/ja.js +1 -1
- package/esm/vs/nls/lang/ko.js +1 -1
- package/esm/vs/nls/lang/pl.js +1 -1
- package/esm/vs/nls/lang/pt-br.js +1 -1
- package/esm/vs/nls/lang/ru.js +1 -1
- package/esm/vs/nls/lang/tr.js +1 -1
- package/esm/vs/nls/lang/zh-cn.js +1 -1
- package/esm/vs/nls/lang/zh-tw.js +1 -1
- package/esm/vs/platform/actionWidget/browser/actionList.js +46 -6
- package/esm/vs/platform/actionWidget/browser/actionWidget.js +9 -2
- package/esm/vs/platform/actions/common/actions.js +2 -1
- package/esm/vs/platform/hover/browser/hoverService.js +1 -0
- package/esm/vs/platform/product/common/product.js +16 -1
- package/min/vs/basic-languages/monaco.contribution.js +1 -1
- package/min/vs/{cssMode-CxJ_Cr_Z.js → cssMode-CheCY05R.js} +1 -1
- package/min/vs/editor/editor.main.css +1 -1
- package/min/vs/editor/editor.main.js +1 -1
- package/min/vs/{editor-CyVlw8K4.js → editor-DxYWA3-X.js} +112 -110
- package/min/vs/editor.js +1 -1
- package/min/vs/{freemarker2-CJcSu3nc.js → freemarker2-C7J7V1Hp.js} +1 -1
- package/min/vs/{handlebars-DPLjS6oj.js → handlebars-DsCar5Ix.js} +1 -1
- package/min/vs/{html-DUmbFRY-.js → html-BGLIaUZV.js} +1 -1
- package/min/vs/{htmlMode-DfUvYWkE.js → htmlMode-BB6WOoy3.js} +1 -1
- package/min/vs/{index-DOycyDud.js → index-BdR0nSqf.js} +1 -1
- package/min/vs/index.js +1 -1
- package/min/vs/{javascript-CQpB78Gy.js → javascript-CXE3i1eX.js} +1 -1
- package/min/vs/{jsonMode-B1E1R3KS.js → jsonMode-rtaE9alu.js} +1 -1
- package/min/vs/language/css/monaco.contribution.js +1 -1
- package/min/vs/language/html/monaco.contribution.js +1 -1
- package/min/vs/language/json/monaco.contribution.js +1 -1
- package/min/vs/language/typescript/monaco.contribution.js +1 -1
- package/min/vs/{liquid-Bh_nhvai.js → liquid-CEdn0ovR.js} +1 -1
- package/min/vs/{lspLanguageFeatures-CAWBopti.js → lspLanguageFeatures-CRAjJmzF.js} +1 -1
- package/min/vs/{mdx-CvpAYI3X.js → mdx-DLDMIqnu.js} +1 -1
- package/min/vs/{monaco.contribution-QIm8iN-Y.js → monaco.contribution-BrRAk-VA.js} +1 -1
- package/min/vs/{monaco.contribution-C3jTRlbI.js → monaco.contribution-C67XgReK.js} +1 -1
- package/min/vs/{monaco.contribution-Cmckd8EG.js → monaco.contribution-CYT-Sx3l.js} +1 -1
- package/min/vs/{monaco.contribution-6Rc9eWJ0.js → monaco.contribution-DjiQkKLa.js} +1 -1
- package/min/vs/nls/lang/cs.js +1 -1
- package/min/vs/nls/lang/de.js +1 -1
- package/min/vs/nls/lang/es.js +1 -1
- package/min/vs/nls/lang/fr.js +1 -1
- package/min/vs/nls/lang/it.js +1 -1
- package/min/vs/nls/lang/ja.js +1 -1
- package/min/vs/nls/lang/ko.js +1 -1
- package/min/vs/nls/lang/pl.js +1 -1
- package/min/vs/nls/lang/pt-br.js +1 -1
- package/min/vs/nls/lang/ru.js +1 -1
- package/min/vs/nls/lang/tr.js +1 -1
- package/min/vs/nls/lang/zh-cn.js +1 -1
- package/min/vs/nls/lang/zh-tw.js +1 -1
- package/min/vs/{python-BuY3uazV.js → python-CKbl_I3e.js} +1 -1
- package/min/vs/{razor-DQBMGsJX.js → razor--RjiPxbd.js} +1 -1
- package/min/vs/{toggleHighContrast-BTse4XBl.js → toggleHighContrast-BKDMxisH.js} +31 -33
- package/min/vs/{tsMode-C8sInOMc.js → tsMode-C48d5M22.js} +1 -1
- package/min/vs/{typescript-DMigl3F4.js → typescript-e7oUhPyX.js} +1 -1
- package/min/vs/{workers-BznOw4bL.js → workers-CtpYUoCo.js} +1 -1
- package/min/vs/{xml-C2bHWkWJ.js → xml-tOyfgws7.js} +1 -1
- package/min/vs/{yaml-gtjQmyMa.js → yaml-Cmf9NYDf.js} +1 -1
- package/monaco.d.ts +5 -1
- package/package.json +4 -4
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
define("vs/tsMode-
|
|
1
|
+
define("vs/tsMode-jpkv3SbL", ["exports", "./ts.worker-CArJhH03", "./editor-CR18QzPP", "./workers-zrUx_2Gw", "./monaco.contribution-CVBrIlxn"], (function(exports, ts_worker, editor, workers, src_deprecated_language_typescript_monaco_contribution_ts) {
|
|
2
2
|
"use strict";
|
|
3
3
|
class WorkerManager {
|
|
4
4
|
constructor(_modeId, _defaults) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
define("vs/typescript-
|
|
1
|
+
define("vs/typescript-f8pt88eA", ["exports", "./editor-CR18QzPP"], (function(exports, editor) {
|
|
2
2
|
"use strict";
|
|
3
3
|
const conf = {
|
|
4
4
|
wordPattern: /(-?\d*\.\d\w*)|([^\`\~\!\@\#\%\^\&\*\(\)\-\=\+\[\{\]\}\\\|\;\:\'\"\,\.\<\>\/\?\s]+)/g,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
define("vs/workers-
|
|
1
|
+
define("vs/workers-zrUx_2Gw", ["exports", "./editor-CR18QzPP", "./toggleHighContrast-CLgtrrIB"], (function(exports, editor, toggleHighContrast) {
|
|
2
2
|
"use strict";
|
|
3
3
|
function createTrustedTypesPolicy(policyName, policyOptions) {
|
|
4
4
|
const monacoEnvironment = globalThis.MonacoEnvironment;
|
|
@@ -498,6 +498,7 @@ function getDomSanitizerConfig(mdStrConfig, options) {
|
|
|
498
498
|
Schemas.vscodeRemote,
|
|
499
499
|
Schemas.vscodeRemoteResource,
|
|
500
500
|
Schemas.vscodeNotebookCell,
|
|
501
|
+
Schemas.vscodeChatPrompt,
|
|
501
502
|
// For links that are handled entirely by the action handler
|
|
502
503
|
Schemas.internal,
|
|
503
504
|
];
|
|
@@ -283,7 +283,10 @@ class ActionViewItem extends BaseActionViewItem {
|
|
|
283
283
|
if (this.cssClass && this.label) {
|
|
284
284
|
this.label.classList.remove(...this.cssClass.split(' '));
|
|
285
285
|
}
|
|
286
|
-
if (this.
|
|
286
|
+
if (this.action.id === Separator.ID && this.action.class) {
|
|
287
|
+
this.label?.classList.add(this.action.class);
|
|
288
|
+
}
|
|
289
|
+
else if (this.options.icon) {
|
|
287
290
|
this.cssClass = this.getClass();
|
|
288
291
|
if (this.label) {
|
|
289
292
|
this.label.classList.add('codicon');
|
|
@@ -45,7 +45,8 @@
|
|
|
45
45
|
height: 16px;
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
-
.monaco-action-bar .action-label
|
|
48
|
+
.monaco-action-bar .action-label,
|
|
49
|
+
.monaco-action-bar .action-item .keybinding {
|
|
49
50
|
display: flex;
|
|
50
51
|
font-size: 11px;
|
|
51
52
|
padding: 3px;
|
|
@@ -75,12 +76,14 @@
|
|
|
75
76
|
display: block;
|
|
76
77
|
}
|
|
77
78
|
|
|
78
|
-
.monaco-action-bar.vertical .action-label.separator {
|
|
79
|
+
.monaco-action-bar.vertical .action-item .action-label.separator {
|
|
79
80
|
display: block;
|
|
80
|
-
border-bottom: 1px solid var(--vscode-disabledForeground);
|
|
81
|
+
border-bottom: 1px solid var(--vscode-menu-separatorBackground, var(--vscode-disabledForeground));
|
|
81
82
|
padding-top: 1px;
|
|
82
|
-
margin
|
|
83
|
-
|
|
83
|
+
margin: 4px .8em;
|
|
84
|
+
width: 100%;
|
|
85
|
+
height: 0;
|
|
86
|
+
background-color: transparent;
|
|
84
87
|
}
|
|
85
88
|
|
|
86
89
|
.monaco-action-bar .action-item .action-label.separator {
|
|
@@ -39,7 +39,7 @@ function layout(viewportSize, viewSize, anchor) {
|
|
|
39
39
|
if (viewSize <= layoutBeforeAnchorBoundary) {
|
|
40
40
|
return layoutBeforeAnchorBoundary - viewSize; // happy case, lay it out before the anchor
|
|
41
41
|
}
|
|
42
|
-
if (viewSize <= viewportSize - layoutAfterAnchorBoundary) {
|
|
42
|
+
if (viewSize <= viewportSize - layoutAfterAnchorBoundary && layoutBeforeAnchorBoundary < viewSize / 2) {
|
|
43
43
|
return layoutAfterAnchorBoundary; // ok case, lay it out after the anchor
|
|
44
44
|
}
|
|
45
45
|
return 0; // sad case, lay it over the anchor
|
|
@@ -2,10 +2,11 @@
|
|
|
2
2
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
3
3
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
|
4
4
|
*--------------------------------------------------------------------------------------------*/
|
|
5
|
+
const NotSelectableGroupId = 'notSelectable';
|
|
5
6
|
class ListError extends Error {
|
|
6
7
|
constructor(user, message) {
|
|
7
8
|
super(`ListError [${user}] ${message}`);
|
|
8
9
|
}
|
|
9
10
|
}
|
|
10
11
|
|
|
11
|
-
export { ListError };
|
|
12
|
+
export { ListError, NotSelectableGroupId };
|
|
@@ -17,7 +17,7 @@ import { clamp } from '../../../common/numbers.js';
|
|
|
17
17
|
import { isMacintosh } from '../../../common/platform.js';
|
|
18
18
|
import { isNumber } from '../../../common/types.js';
|
|
19
19
|
import './list.css';
|
|
20
|
-
import { ListError } from './list.js';
|
|
20
|
+
import { ListError, NotSelectableGroupId } from './list.js';
|
|
21
21
|
import { ListView } from './listView.js';
|
|
22
22
|
import { StandardMouseEvent } from '../../mouseEvent.js';
|
|
23
23
|
import '../../../common/observableInternal/index.js';
|
|
@@ -319,7 +319,14 @@ class KeyboardController {
|
|
|
319
319
|
onCtrlA(e) {
|
|
320
320
|
e.preventDefault();
|
|
321
321
|
e.stopPropagation();
|
|
322
|
-
|
|
322
|
+
let selection = range(this.list.length);
|
|
323
|
+
// Filter by group if identity provider has getGroupId
|
|
324
|
+
const focusedElements = this.list.getFocus();
|
|
325
|
+
const referenceGroupId = focusedElements.length > 0 ? this.list.getElementGroupId(focusedElements[0]) : undefined;
|
|
326
|
+
if (referenceGroupId !== undefined) {
|
|
327
|
+
selection = this.list.filterIndicesByGroup(selection, referenceGroupId);
|
|
328
|
+
}
|
|
329
|
+
this.list.setSelection(selection, e.browserEvent);
|
|
323
330
|
this.list.setAnchor(undefined);
|
|
324
331
|
this.view.domNode.focus();
|
|
325
332
|
}
|
|
@@ -614,7 +621,11 @@ class MouseController {
|
|
|
614
621
|
this.list.setFocus([focus], e.browserEvent);
|
|
615
622
|
this.list.setAnchor(focus);
|
|
616
623
|
if (!isMouseRightClick(e.browserEvent)) {
|
|
617
|
-
|
|
624
|
+
// Check if the element is selectable (getGroupId must not return undefined)
|
|
625
|
+
const focusGroupId = this.list.getElementGroupId(focus);
|
|
626
|
+
if (focusGroupId !== NotSelectableGroupId) {
|
|
627
|
+
this.list.setSelection([focus], e.browserEvent);
|
|
628
|
+
}
|
|
618
629
|
}
|
|
619
630
|
this._onPointer.fire(e);
|
|
620
631
|
}
|
|
@@ -643,7 +654,14 @@ class MouseController {
|
|
|
643
654
|
}
|
|
644
655
|
const min = Math.min(anchor, focus);
|
|
645
656
|
const max = Math.max(anchor, focus);
|
|
646
|
-
|
|
657
|
+
let rangeSelection = range(min, max + 1);
|
|
658
|
+
const selectedElement = this.list.getSelection()[0];
|
|
659
|
+
if (selectedElement !== undefined) {
|
|
660
|
+
const referenceGroupId = this.list.getElementGroupId(selectedElement);
|
|
661
|
+
if (referenceGroupId !== undefined) {
|
|
662
|
+
rangeSelection = this.list.filterIndicesByGroup(rangeSelection, referenceGroupId);
|
|
663
|
+
}
|
|
664
|
+
}
|
|
647
665
|
const selection = this.list.getSelection();
|
|
648
666
|
const contiguousRange = getContiguousRangeContaining(disjunction(selection, [anchor]), anchor);
|
|
649
667
|
if (contiguousRange.length === 0) {
|
|
@@ -658,8 +676,15 @@ class MouseController {
|
|
|
658
676
|
const newSelection = selection.filter(i => i !== focus);
|
|
659
677
|
this.list.setFocus([focus]);
|
|
660
678
|
this.list.setAnchor(focus);
|
|
679
|
+
const focusGroupId = this.list.getElementGroupId(focus);
|
|
680
|
+
if (focusGroupId === NotSelectableGroupId) {
|
|
681
|
+
return; // Cannot select this element, do nothing
|
|
682
|
+
}
|
|
661
683
|
if (selection.length === newSelection.length) {
|
|
662
|
-
|
|
684
|
+
const itemsToBeSelected = focusGroupId !== undefined ?
|
|
685
|
+
this.list.filterIndicesByGroup([...newSelection, focus], focusGroupId)
|
|
686
|
+
: [...newSelection, focus];
|
|
687
|
+
this.list.setSelection(itemsToBeSelected, e.browserEvent);
|
|
663
688
|
}
|
|
664
689
|
else {
|
|
665
690
|
this.list.setSelection(newSelection, e.browserEvent);
|
|
@@ -1257,6 +1282,7 @@ class List {
|
|
|
1257
1282
|
throw new ListError(this.user, `Invalid index ${index}`);
|
|
1258
1283
|
}
|
|
1259
1284
|
}
|
|
1285
|
+
indexes = indexes.filter(i => this.getElementGroupId(i) !== NotSelectableGroupId);
|
|
1260
1286
|
this.selection.set(indexes, browserEvent);
|
|
1261
1287
|
}
|
|
1262
1288
|
getSelection() {
|
|
@@ -1282,6 +1308,37 @@ class List {
|
|
|
1282
1308
|
const anchor = this.getAnchor();
|
|
1283
1309
|
return typeof anchor === 'undefined' ? undefined : this.element(anchor);
|
|
1284
1310
|
}
|
|
1311
|
+
/**
|
|
1312
|
+
* Gets the group ID for an element at the given index.
|
|
1313
|
+
* Returns undefined if no identity provider, no getGroupId method, or if the group ID is undefined.
|
|
1314
|
+
*/
|
|
1315
|
+
getElementGroupId(index) {
|
|
1316
|
+
const identityProvider = this.options.identityProvider;
|
|
1317
|
+
if (!identityProvider?.getGroupId) {
|
|
1318
|
+
return undefined;
|
|
1319
|
+
}
|
|
1320
|
+
const element = this.element(index);
|
|
1321
|
+
return identityProvider.getGroupId(element);
|
|
1322
|
+
}
|
|
1323
|
+
/**
|
|
1324
|
+
* Filters the given indices to only include those with a matching group ID.
|
|
1325
|
+
* If no identity provider or getGroupId method exists, returns the original indices.
|
|
1326
|
+
* If referenceGroupId is undefined, returns an empty array (elements without group IDs are not selectable).
|
|
1327
|
+
*/
|
|
1328
|
+
filterIndicesByGroup(indices, referenceGroupId) {
|
|
1329
|
+
const identityProvider = this.options.identityProvider;
|
|
1330
|
+
if (!identityProvider?.getGroupId) {
|
|
1331
|
+
return indices;
|
|
1332
|
+
}
|
|
1333
|
+
if (referenceGroupId === NotSelectableGroupId) {
|
|
1334
|
+
return [];
|
|
1335
|
+
}
|
|
1336
|
+
return indices.filter(index => {
|
|
1337
|
+
const element = this.element(index);
|
|
1338
|
+
const groupId = identityProvider.getGroupId(element);
|
|
1339
|
+
return groupId === referenceGroupId;
|
|
1340
|
+
});
|
|
1341
|
+
}
|
|
1285
1342
|
setFocus(indexes, browserEvent) {
|
|
1286
1343
|
for (const index of indexes) {
|
|
1287
1344
|
if (index < 0 || index >= this.length) {
|
|
@@ -131,7 +131,10 @@ function asListOptions(modelProvider, disposableStore, options) {
|
|
|
131
131
|
identityProvider: options.identityProvider && {
|
|
132
132
|
getId(el) {
|
|
133
133
|
return options.identityProvider.getId(el.element);
|
|
134
|
-
}
|
|
134
|
+
},
|
|
135
|
+
getGroupId: options.identityProvider.getGroupId ? (el) => {
|
|
136
|
+
return options.identityProvider.getGroupId(el.element);
|
|
137
|
+
} : undefined
|
|
135
138
|
},
|
|
136
139
|
dnd: options.dnd && disposableStore.add(new TreeNodeListDragAndDrop(modelProvider, options.dnd)),
|
|
137
140
|
multipleSelectionController: options.multipleSelectionController && {
|
|
@@ -210,7 +210,10 @@ function asObjectTreeOptions(options) {
|
|
|
210
210
|
identityProvider: options.identityProvider && {
|
|
211
211
|
getId(el) {
|
|
212
212
|
return options.identityProvider.getId(el.element);
|
|
213
|
-
}
|
|
213
|
+
},
|
|
214
|
+
getGroupId: options.identityProvider.getGroupId ? (el) => {
|
|
215
|
+
return options.identityProvider.getGroupId(el.element);
|
|
216
|
+
} : undefined
|
|
214
217
|
},
|
|
215
218
|
dnd: options.dnd && new AsyncDataTreeNodeListDragAndDrop(options.dnd),
|
|
216
219
|
multipleSelectionController: options.multipleSelectionController && {
|
|
@@ -1,55 +1,42 @@
|
|
|
1
1
|
import { isWindows } from '../../../../base/common/platform.js';
|
|
2
2
|
import { Mimes } from '../../../../base/common/mime.js';
|
|
3
|
-
import { LogLevel } from '../../../../platform/log/common/log.js';
|
|
4
3
|
import { generateUuid } from '../../../../base/common/uuid.js';
|
|
4
|
+
import { toExternalVSDataTransfer } from '../../dataTransfer.js';
|
|
5
5
|
|
|
6
|
-
function
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
//
|
|
15
|
-
|
|
16
|
-
// execCommand('copy') does not always work (it does not fire a clipboard event)
|
|
17
|
-
// !!!!!
|
|
18
|
-
// We signal that we have executed a copy command
|
|
19
|
-
CopyOptions.electronBugWorkaroundCopyEventHasFired = true;
|
|
20
|
-
e.preventDefault();
|
|
21
|
-
if (e.clipboardData) {
|
|
22
|
-
ClipboardEventUtils.setTextData(e.clipboardData, dataToCopy.text, dataToCopy.html, storedMetadata);
|
|
23
|
-
}
|
|
24
|
-
logService.trace('ensureClipboardGetsEditorSelection with id : ', id, ' with text.length: ', dataToCopy.text.length);
|
|
6
|
+
function generateDataToCopyAndStoreInMemory(viewModel, id, isFirefox) {
|
|
7
|
+
const { dataToCopy, metadata } = generateDataToCopy(viewModel);
|
|
8
|
+
storeMetadataInMemory(dataToCopy.text, metadata, isFirefox);
|
|
9
|
+
return { dataToCopy, metadata };
|
|
10
|
+
}
|
|
11
|
+
function storeMetadataInMemory(textToCopy, metadata, isFirefox) {
|
|
12
|
+
InMemoryClipboardMetadataManager.INSTANCE.set(
|
|
13
|
+
// When writing "LINE\r\n" to the clipboard and then pasting,
|
|
14
|
+
// Firefox pastes "LINE\n", so let's work around this quirk
|
|
15
|
+
(isFirefox ? textToCopy.replace(/\r\n/g, '\n') : textToCopy), metadata);
|
|
25
16
|
}
|
|
26
|
-
function
|
|
27
|
-
const emptySelectionClipboard =
|
|
28
|
-
const copyWithSyntaxHighlighting =
|
|
17
|
+
function generateDataToCopy(viewModel) {
|
|
18
|
+
const emptySelectionClipboard = viewModel.getEditorOption(45 /* EditorOption.emptySelectionClipboard */);
|
|
19
|
+
const copyWithSyntaxHighlighting = viewModel.getEditorOption(31 /* EditorOption.copyWithSyntaxHighlighting */);
|
|
29
20
|
const selections = viewModel.getCursorStates().map(cursorState => cursorState.modelState.selection);
|
|
30
21
|
const dataToCopy = getDataToCopy(viewModel, selections, emptySelectionClipboard, copyWithSyntaxHighlighting);
|
|
31
|
-
const
|
|
22
|
+
const metadata = {
|
|
32
23
|
version: 1,
|
|
33
|
-
id,
|
|
24
|
+
id: generateUuid(),
|
|
34
25
|
isFromEmptySelection: dataToCopy.isFromEmptySelection,
|
|
35
26
|
multicursorText: dataToCopy.multicursorText,
|
|
36
27
|
mode: dataToCopy.mode
|
|
37
28
|
};
|
|
38
|
-
|
|
39
|
-
// When writing "LINE\r\n" to the clipboard and then pasting,
|
|
40
|
-
// Firefox pastes "LINE\n", so let's work around this quirk
|
|
41
|
-
(isFirefox ? dataToCopy.text.replace(/\r\n/g, '\n') : dataToCopy.text), storedMetadata);
|
|
42
|
-
return { dataToCopy, storedMetadata };
|
|
29
|
+
return { dataToCopy, metadata };
|
|
43
30
|
}
|
|
44
31
|
function getDataToCopy(viewModel, modelSelections, emptySelectionClipboard, copyWithSyntaxHighlighting) {
|
|
45
|
-
const
|
|
32
|
+
const { sourceRanges, sourceText } = viewModel.getPlainTextToCopy(modelSelections, emptySelectionClipboard, isWindows);
|
|
46
33
|
const newLineCharacter = viewModel.model.getEOL();
|
|
47
34
|
const isFromEmptySelection = (emptySelectionClipboard && modelSelections.length === 1 && modelSelections[0].isEmpty());
|
|
48
|
-
const multicursorText = (Array.isArray(
|
|
49
|
-
const text = (Array.isArray(
|
|
35
|
+
const multicursorText = (Array.isArray(sourceText) ? sourceText : null);
|
|
36
|
+
const text = (Array.isArray(sourceText) ? sourceText.join(newLineCharacter) : sourceText);
|
|
50
37
|
let html = undefined;
|
|
51
38
|
let mode = null;
|
|
52
|
-
if (CopyOptions.forceCopyWithSyntaxHighlighting || (copyWithSyntaxHighlighting &&
|
|
39
|
+
if (CopyOptions.forceCopyWithSyntaxHighlighting || (copyWithSyntaxHighlighting && sourceText.length < 65536)) {
|
|
53
40
|
const richText = viewModel.getRichTextToCopy(modelSelections, emptySelectionClipboard);
|
|
54
41
|
if (richText) {
|
|
55
42
|
html = richText.html;
|
|
@@ -58,6 +45,7 @@ function getDataToCopy(viewModel, modelSelections, emptySelectionClipboard, copy
|
|
|
58
45
|
}
|
|
59
46
|
const dataToCopy = {
|
|
60
47
|
isFromEmptySelection,
|
|
48
|
+
sourceRanges,
|
|
61
49
|
multicursorText,
|
|
62
50
|
text,
|
|
63
51
|
html,
|
|
@@ -122,5 +110,63 @@ const ClipboardEventUtils = {
|
|
|
122
110
|
clipboardData.setData('vscode-editor-data', JSON.stringify(metadata));
|
|
123
111
|
}
|
|
124
112
|
};
|
|
113
|
+
/**
|
|
114
|
+
* Creates an IClipboardCopyEvent from a DOM ClipboardEvent.
|
|
115
|
+
*/
|
|
116
|
+
function createClipboardCopyEvent(e, isCut, context, logService, isFirefox) {
|
|
117
|
+
const { dataToCopy, metadata } = generateDataToCopy(context.viewModel);
|
|
118
|
+
let handled = false;
|
|
119
|
+
return {
|
|
120
|
+
isCut,
|
|
121
|
+
clipboardData: {
|
|
122
|
+
setData: (type, value) => {
|
|
123
|
+
e.clipboardData?.setData(type, value);
|
|
124
|
+
},
|
|
125
|
+
},
|
|
126
|
+
dataToCopy,
|
|
127
|
+
ensureClipboardGetsEditorData: () => {
|
|
128
|
+
e.preventDefault();
|
|
129
|
+
if (e.clipboardData) {
|
|
130
|
+
ClipboardEventUtils.setTextData(e.clipboardData, dataToCopy.text, dataToCopy.html, metadata);
|
|
131
|
+
}
|
|
132
|
+
storeMetadataInMemory(dataToCopy.text, metadata, isFirefox);
|
|
133
|
+
logService.trace('ensureClipboardGetsEditorSelection with id : ', metadata.id, ' with text.length: ', dataToCopy.text.length);
|
|
134
|
+
},
|
|
135
|
+
setHandled: () => {
|
|
136
|
+
handled = true;
|
|
137
|
+
e.preventDefault();
|
|
138
|
+
e.stopImmediatePropagation();
|
|
139
|
+
},
|
|
140
|
+
get isHandled() { return handled; },
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Creates an IClipboardPasteEvent from a DOM ClipboardEvent.
|
|
145
|
+
*/
|
|
146
|
+
function createClipboardPasteEvent(e) {
|
|
147
|
+
let handled = false;
|
|
148
|
+
let [text, metadata] = e.clipboardData ? ClipboardEventUtils.getTextData(e.clipboardData) : ['', null];
|
|
149
|
+
metadata = metadata || InMemoryClipboardMetadataManager.INSTANCE.get(text);
|
|
150
|
+
return {
|
|
151
|
+
clipboardData: createReadableClipboardData(e.clipboardData),
|
|
152
|
+
metadata,
|
|
153
|
+
text,
|
|
154
|
+
toExternalVSDataTransfer: () => e.clipboardData ? toExternalVSDataTransfer(e.clipboardData) : undefined,
|
|
155
|
+
browserEvent: e,
|
|
156
|
+
setHandled: () => {
|
|
157
|
+
handled = true;
|
|
158
|
+
e.preventDefault();
|
|
159
|
+
e.stopImmediatePropagation();
|
|
160
|
+
},
|
|
161
|
+
get isHandled() { return handled; },
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
function createReadableClipboardData(dataTransfer) {
|
|
165
|
+
return {
|
|
166
|
+
types: Array.from(dataTransfer?.types ?? []),
|
|
167
|
+
files: Array.prototype.slice.call(dataTransfer?.files ?? [], 0),
|
|
168
|
+
getData: (type) => dataTransfer?.getData(type) ?? '',
|
|
169
|
+
};
|
|
170
|
+
}
|
|
125
171
|
|
|
126
|
-
export {
|
|
172
|
+
export { CopyOptions, InMemoryClipboardMetadataManager, createClipboardCopyEvent, createClipboardPasteEvent, createReadableClipboardData, generateDataToCopyAndStoreInMemory };
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { Emitter } from '../../../../base/common/event.js';
|
|
1
2
|
import { ViewPart } from '../../view/viewPart.js';
|
|
2
3
|
|
|
3
4
|
/*---------------------------------------------------------------------------------------------
|
|
@@ -5,6 +6,16 @@ import { ViewPart } from '../../view/viewPart.js';
|
|
|
5
6
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
|
6
7
|
*--------------------------------------------------------------------------------------------*/
|
|
7
8
|
class AbstractEditContext extends ViewPart {
|
|
9
|
+
constructor() {
|
|
10
|
+
super(...arguments);
|
|
11
|
+
// Clipboard events - emitted before the default clipboard handling
|
|
12
|
+
this._onWillCopy = this._register(new Emitter());
|
|
13
|
+
this.onWillCopy = this._onWillCopy.event;
|
|
14
|
+
this._onWillCut = this._register(new Emitter());
|
|
15
|
+
this.onWillCut = this._onWillCut.event;
|
|
16
|
+
this._onWillPaste = this._register(new Emitter());
|
|
17
|
+
this.onWillPaste = this._onWillPaste.event;
|
|
18
|
+
}
|
|
8
19
|
}
|
|
9
20
|
|
|
10
21
|
export { AbstractEditContext };
|
|
@@ -4,7 +4,7 @@ import { getWindow, addDisposableListener, getActiveElement, getWindowId } from
|
|
|
4
4
|
import { FastDomNode } from '../../../../../base/browser/fastDomNode.js';
|
|
5
5
|
import { StandardKeyboardEvent } from '../../../../../base/browser/keyboardEvent.js';
|
|
6
6
|
import { IInstantiationService } from '../../../../../platform/instantiation/common/instantiation.js';
|
|
7
|
-
import {
|
|
7
|
+
import { CopyOptions, createClipboardCopyEvent, createClipboardPasteEvent } from '../clipboardUtils.js';
|
|
8
8
|
import { AbstractEditContext } from '../editContext.js';
|
|
9
9
|
import { FocusTracker, editContextAddDisposableListener } from './nativeEditContextUtils.js';
|
|
10
10
|
import { ScreenReaderSupport } from './screenReaderSupport.js';
|
|
@@ -81,14 +81,30 @@ let NativeEditContext = class NativeEditContext extends AbstractEditContext {
|
|
|
81
81
|
this._screenReaderSupport = this._register(instantiationService.createInstance(ScreenReaderSupport, this.domNode, context, this._viewController));
|
|
82
82
|
this._register(addDisposableListener(this.domNode.domNode, 'copy', (e) => {
|
|
83
83
|
this.logService.trace('NativeEditContext#copy');
|
|
84
|
-
|
|
84
|
+
// !!!!!
|
|
85
|
+
// This is a workaround for what we think is an Electron bug where
|
|
86
|
+
// execCommand('copy') does not always work (it does not fire a clipboard event)
|
|
87
|
+
// !!!!!
|
|
88
|
+
// We signal that we have executed a copy command
|
|
89
|
+
CopyOptions.electronBugWorkaroundCopyEventHasFired = true;
|
|
90
|
+
const copyEvent = createClipboardCopyEvent(e, /* isCut */ false, this._context, this.logService, isFirefox);
|
|
91
|
+
this._onWillCopy.fire(copyEvent);
|
|
92
|
+
if (copyEvent.isHandled) {
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
copyEvent.ensureClipboardGetsEditorData();
|
|
85
96
|
}));
|
|
86
97
|
this._register(addDisposableListener(this.domNode.domNode, 'cut', (e) => {
|
|
87
98
|
this.logService.trace('NativeEditContext#cut');
|
|
99
|
+
const cutEvent = createClipboardCopyEvent(e, /* isCut */ true, this._context, this.logService, isFirefox);
|
|
100
|
+
this._onWillCut.fire(cutEvent);
|
|
101
|
+
if (cutEvent.isHandled) {
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
88
104
|
// Pretend here we touched the text area, as the `cut` event will most likely
|
|
89
105
|
// result in a `selectionchange` event which we want to ignore
|
|
90
106
|
this._screenReaderSupport.onWillCut();
|
|
91
|
-
|
|
107
|
+
cutEvent.ensureClipboardGetsEditorData();
|
|
92
108
|
this.logService.trace('NativeEditContext#cut (before viewController.cut)');
|
|
93
109
|
this._viewController.cut();
|
|
94
110
|
}));
|
|
@@ -107,28 +123,32 @@ let NativeEditContext = class NativeEditContext extends AbstractEditContext {
|
|
|
107
123
|
}));
|
|
108
124
|
this._register(addDisposableListener(this.domNode.domNode, 'paste', (e) => {
|
|
109
125
|
this.logService.trace('NativeEditContext#paste');
|
|
126
|
+
const pasteEvent = createClipboardPasteEvent(e);
|
|
127
|
+
this._onWillPaste.fire(pasteEvent);
|
|
128
|
+
if (pasteEvent.isHandled) {
|
|
129
|
+
e.preventDefault();
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
110
132
|
e.preventDefault();
|
|
111
133
|
if (!e.clipboardData) {
|
|
112
134
|
return;
|
|
113
135
|
}
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
if (!text) {
|
|
136
|
+
this.logService.trace('NativeEditContext#paste with id : ', pasteEvent.metadata?.id, ' with text.length: ', pasteEvent.text.length);
|
|
137
|
+
if (!pasteEvent.text) {
|
|
117
138
|
return;
|
|
118
139
|
}
|
|
119
|
-
metadata = metadata || InMemoryClipboardMetadataManager.INSTANCE.get(text);
|
|
120
140
|
let pasteOnNewLine = false;
|
|
121
141
|
let multicursorText = null;
|
|
122
142
|
let mode = null;
|
|
123
|
-
if (metadata) {
|
|
143
|
+
if (pasteEvent.metadata) {
|
|
124
144
|
const options = this._context.configuration.options;
|
|
125
145
|
const emptySelectionClipboard = options.get(45 /* EditorOption.emptySelectionClipboard */);
|
|
126
|
-
pasteOnNewLine = emptySelectionClipboard && !!metadata.isFromEmptySelection;
|
|
127
|
-
multicursorText = typeof metadata.multicursorText !== 'undefined' ? metadata.multicursorText : null;
|
|
128
|
-
mode = metadata.mode;
|
|
146
|
+
pasteOnNewLine = emptySelectionClipboard && !!pasteEvent.metadata.isFromEmptySelection;
|
|
147
|
+
multicursorText = typeof pasteEvent.metadata.multicursorText !== 'undefined' ? pasteEvent.metadata.multicursorText : null;
|
|
148
|
+
mode = pasteEvent.metadata.mode;
|
|
129
149
|
}
|
|
130
150
|
this.logService.trace('NativeEditContext#paste (before viewController.paste)');
|
|
131
|
-
this._viewController.paste(text, pasteOnNewLine, multicursorText, mode);
|
|
151
|
+
this._viewController.paste(pasteEvent.text, pasteOnNewLine, multicursorText, mode);
|
|
132
152
|
}));
|
|
133
153
|
// Edit context events
|
|
134
154
|
this._register(editContextAddDisposableListener(this._editContext, 'textformatupdate', (e) => this._handleTextFormatUpdate(e)));
|
|
@@ -260,15 +280,15 @@ let NativeEditContext = class NativeEditContext extends AbstractEditContext {
|
|
|
260
280
|
onZonesChanged(e) {
|
|
261
281
|
return true;
|
|
262
282
|
}
|
|
263
|
-
|
|
264
|
-
this.logService.trace('NativeEditContext#
|
|
265
|
-
this.
|
|
283
|
+
handleWillPaste() {
|
|
284
|
+
this.logService.trace('NativeEditContext#handleWillPaste');
|
|
285
|
+
this._prepareScreenReaderForPaste();
|
|
266
286
|
}
|
|
267
|
-
|
|
287
|
+
_prepareScreenReaderForPaste() {
|
|
268
288
|
this._screenReaderSupport.onWillPaste();
|
|
269
289
|
}
|
|
270
|
-
|
|
271
|
-
this.logService.trace('NativeEditContext#
|
|
290
|
+
handleWillCopy() {
|
|
291
|
+
this.logService.trace('NativeEditContext#handleWillCopy');
|
|
272
292
|
this.logService.trace('NativeEditContext#isFocused : ', this.domNode.domNode === getActiveElement());
|
|
273
293
|
}
|
|
274
294
|
writeScreenReaderContent() {
|
|
@@ -205,6 +205,10 @@ let TextAreaEditContext = class TextAreaEditContext extends AbstractEditContext
|
|
|
205
205
|
isFirefox: isFirefox,
|
|
206
206
|
isSafari: isSafari,
|
|
207
207
|
}));
|
|
208
|
+
// Relay clipboard events from TextAreaInput
|
|
209
|
+
this._register(this._textAreaInput.onWillCopy(e => this._onWillCopy.fire(e)));
|
|
210
|
+
this._register(this._textAreaInput.onWillCut(e => this._onWillCut.fire(e)));
|
|
211
|
+
this._register(this._textAreaInput.onWillPaste(e => this._onWillPaste.fire(e)));
|
|
208
212
|
this._register(this._textAreaInput.onKeyDown((e) => {
|
|
209
213
|
this._viewController.emitKeyDown(e);
|
|
210
214
|
}));
|
|
@@ -10,7 +10,7 @@ import { isHighSurrogate } from '../../../../../base/common/strings.js';
|
|
|
10
10
|
import { Selection } from '../../../../common/core/selection.js';
|
|
11
11
|
import { IAccessibilityService } from '../../../../../platform/accessibility/common/accessibility.js';
|
|
12
12
|
import { ILogService } from '../../../../../platform/log/common/log.js';
|
|
13
|
-
import { InMemoryClipboardMetadataManager,
|
|
13
|
+
import { InMemoryClipboardMetadataManager, createClipboardCopyEvent, CopyOptions, createClipboardPasteEvent } from '../clipboardUtils.js';
|
|
14
14
|
import { TextAreaState } from './textAreaEditContextState.js';
|
|
15
15
|
|
|
16
16
|
/*---------------------------------------------------------------------------------------------
|
|
@@ -78,6 +78,12 @@ let TextAreaInput = class TextAreaInput extends Disposable {
|
|
|
78
78
|
this.onCut = this._onCut.event;
|
|
79
79
|
this._onPaste = this._register(new Emitter());
|
|
80
80
|
this.onPaste = this._onPaste.event;
|
|
81
|
+
this._onWillCopy = this._register(new Emitter());
|
|
82
|
+
this.onWillCopy = this._onWillCopy.event;
|
|
83
|
+
this._onWillCut = this._register(new Emitter());
|
|
84
|
+
this.onWillCut = this._onWillCut.event;
|
|
85
|
+
this._onWillPaste = this._register(new Emitter());
|
|
86
|
+
this.onWillPaste = this._onWillPaste.event;
|
|
81
87
|
this._onType = this._register(new Emitter());
|
|
82
88
|
this.onType = this._onType.event;
|
|
83
89
|
this._onCompositionStart = this._register(new Emitter());
|
|
@@ -238,40 +244,57 @@ let TextAreaInput = class TextAreaInput extends Disposable {
|
|
|
238
244
|
// --- Clipboard operations
|
|
239
245
|
this._register(this._textArea.onCut((e) => {
|
|
240
246
|
this._logService.trace(`TextAreaInput#onCut`, e);
|
|
247
|
+
// Fire onWillCut event to allow interception
|
|
248
|
+
const cutEvent = createClipboardCopyEvent(e, /* isCut */ true, this._host.context, this._logService, this._browser.isFirefox);
|
|
249
|
+
this._onWillCut.fire(cutEvent);
|
|
250
|
+
if (cutEvent.isHandled) {
|
|
251
|
+
// Event was handled externally, skip default processing
|
|
252
|
+
return;
|
|
253
|
+
}
|
|
241
254
|
// Pretend here we touched the text area, as the `cut` event will most likely
|
|
242
255
|
// result in a `selectionchange` event which we want to ignore
|
|
243
256
|
this._textArea.setIgnoreSelectionChangeTime('received cut event');
|
|
244
|
-
|
|
245
|
-
ensureClipboardGetsEditorSelection(e, this._host.context, this._logService, this._browser.isFirefox);
|
|
246
|
-
}
|
|
257
|
+
cutEvent.ensureClipboardGetsEditorData();
|
|
247
258
|
this._asyncTriggerCut.schedule();
|
|
248
259
|
}));
|
|
249
260
|
this._register(this._textArea.onCopy((e) => {
|
|
250
261
|
this._logService.trace(`TextAreaInput#onCopy`, e);
|
|
251
|
-
|
|
252
|
-
|
|
262
|
+
// !!!!!
|
|
263
|
+
// This is a workaround for what we think is an Electron bug where
|
|
264
|
+
// execCommand('copy') does not always work (it does not fire a clipboard event)
|
|
265
|
+
// !!!!!
|
|
266
|
+
// We signal that we have executed a copy command
|
|
267
|
+
CopyOptions.electronBugWorkaroundCopyEventHasFired = true;
|
|
268
|
+
// Fire onWillCopy event to allow interception
|
|
269
|
+
const copyEvent = createClipboardCopyEvent(e, /* isCut */ false, this._host.context, this._logService, this._browser.isFirefox);
|
|
270
|
+
this._onWillCopy.fire(copyEvent);
|
|
271
|
+
if (copyEvent.isHandled) {
|
|
272
|
+
// Event was handled externally, skip default processing
|
|
273
|
+
return;
|
|
253
274
|
}
|
|
275
|
+
copyEvent.ensureClipboardGetsEditorData();
|
|
254
276
|
}));
|
|
255
277
|
this._register(this._textArea.onPaste((e) => {
|
|
256
278
|
this._logService.trace(`TextAreaInput#onPaste`, e);
|
|
279
|
+
// Fire onWillPaste event to allow interception
|
|
280
|
+
const pasteEvent = createClipboardPasteEvent(e);
|
|
281
|
+
this._onWillPaste.fire(pasteEvent);
|
|
282
|
+
if (pasteEvent.isHandled) {
|
|
283
|
+
// Event was handled externally, skip default processing
|
|
284
|
+
return;
|
|
285
|
+
}
|
|
257
286
|
// Pretend here we touched the text area, as the `paste` event will most likely
|
|
258
287
|
// result in a `selectionchange` event which we want to ignore
|
|
259
288
|
this._textArea.setIgnoreSelectionChangeTime('received paste event');
|
|
260
289
|
e.preventDefault();
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
}
|
|
264
|
-
let [text, metadata] = ClipboardEventUtils.getTextData(e.clipboardData);
|
|
265
|
-
this._logService.trace(`TextAreaInput#onPaste with id : `, metadata?.id, ' with text.length: ', text.length);
|
|
266
|
-
if (!text) {
|
|
290
|
+
this._logService.trace(`TextAreaInput#onPaste with id : `, pasteEvent.metadata?.id, ' with text.length: ', pasteEvent.text.length);
|
|
291
|
+
if (!pasteEvent.text) {
|
|
267
292
|
return;
|
|
268
293
|
}
|
|
269
|
-
// try the in-memory store
|
|
270
|
-
metadata = metadata || InMemoryClipboardMetadataManager.INSTANCE.get(text);
|
|
271
294
|
this._logService.trace(`TextAreaInput#onPaste (before onPaste)`);
|
|
272
295
|
this._onPaste.fire({
|
|
273
|
-
text: text,
|
|
274
|
-
metadata: metadata
|
|
296
|
+
text: pasteEvent.text,
|
|
297
|
+
metadata: pasteEvent.metadata
|
|
275
298
|
});
|
|
276
299
|
}));
|
|
277
300
|
this._register(this._textArea.onFocus(() => {
|