Merge branch 'main' into benibenj/hideTabsActionBar

This commit is contained in:
Benjamin Pasero
2023-11-01 16:48:16 +01:00
117 changed files with 1051 additions and 634 deletions
+2 -1
View File
@@ -7,6 +7,7 @@
"github.vscode-pull-request-github",
"ms-vscode.vscode-github-issue-notebooks",
"ms-vscode.vscode-selfhost-test-provider",
"ms-vscode.extension-test-runner"
"ms-vscode.extension-test-runner",
"jrieken.vscode-pr-pinger"
]
}
+1 -1
View File
@@ -7,7 +7,7 @@
{
"kind": 2,
"language": "github-issues",
"value": "$repo=repo:microsoft/vscode\n$milestone=milestone:\"October 2023\"\n"
"value": "$repo=repo:microsoft/vscode\n$milestone=milestone:\"November 2023\"\n"
},
{
"kind": 1,
+1 -1
View File
@@ -7,7 +7,7 @@
{
"kind": 2,
"language": "github-issues",
"value": "$REPOS=repo:microsoft/vscode repo:microsoft/vscode-remote-release repo:microsoft/vscode-copilot repo:microsoft/vscode-copilot-release repo:microsoft/vscode-js-debug repo:microsoft/vscode-pull-request-github repo:microsoft/vscode-github-issue-notebooks repo:microsoft/vscode-internalbacklog repo:microsoft/vscode-dev repo:microsoft/vscode-unpkg repo:microsoft/vscode-references-view repo:microsoft/vscode-anycode repo:microsoft/vscode-hexeditor repo:microsoft/vscode-extension-telemetry repo:microsoft/vscode-livepreview repo:microsoft/vscode-remotehub repo:microsoft/vscode-settings-sync-server repo:microsoft/vscode-remote-repositories-github repo:microsoft/monaco-editor repo:microsoft/vscode-vsce repo:microsoft/vscode-dev-chrome-launcher repo:microsoft/vscode-emmet-helper repo:microsoft/vscode-livepreview repo:microsoft/vscode-livepreview repo:microsoft/vscode-python repo:microsoft/vscode-python-debugger repo:microsoft/vscode-jupyter repo:microsoft/vscode-jupyter-internal repo:microsoft/vscode-github-issue-notebooks repo:microsoft/vscode-l10n repo:microsoft/vscode-remote-tunnels repo:microsoft/vscode-pylint repo:microsoft/vscode-black-formatter repo:microsoft/vscode-isort repo:microsoft/lsprotocol repo:microsoft/vscode-flake8 repo:microsoft/vscode-autopep8 repo:microsoft/vscode-python-tools-extension-template repo:microsoft/vscode-mypy repo:microsoft/vscode-python-debugger\n\n$MILESTONE=milestone:\"October 2023\"\n"
"value": "$REPOS=repo:microsoft/vscode repo:microsoft/vscode-remote-release repo:microsoft/vscode-copilot repo:microsoft/vscode-copilot-release repo:microsoft/vscode-js-debug repo:microsoft/vscode-pull-request-github repo:microsoft/vscode-github-issue-notebooks repo:microsoft/vscode-internalbacklog repo:microsoft/vscode-dev repo:microsoft/vscode-unpkg repo:microsoft/vscode-references-view repo:microsoft/vscode-anycode repo:microsoft/vscode-hexeditor repo:microsoft/vscode-extension-telemetry repo:microsoft/vscode-livepreview repo:microsoft/vscode-remotehub repo:microsoft/vscode-settings-sync-server repo:microsoft/vscode-remote-repositories-github repo:microsoft/monaco-editor repo:microsoft/vscode-vsce repo:microsoft/vscode-dev-chrome-launcher repo:microsoft/vscode-emmet-helper repo:microsoft/vscode-livepreview repo:microsoft/vscode-livepreview repo:microsoft/vscode-python repo:microsoft/vscode-python-debugger repo:microsoft/vscode-jupyter repo:microsoft/vscode-jupyter-internal repo:microsoft/vscode-github-issue-notebooks repo:microsoft/vscode-l10n repo:microsoft/vscode-remote-tunnels repo:microsoft/vscode-pylint repo:microsoft/vscode-black-formatter repo:microsoft/vscode-isort repo:microsoft/lsprotocol repo:microsoft/vscode-flake8 repo:microsoft/vscode-autopep8 repo:microsoft/vscode-python-tools-extension-template repo:microsoft/vscode-mypy repo:microsoft/vscode-python-debugger\n\n$MILESTONE=milestone:\"November 2023\"\n"
},
{
"kind": 1,
+1 -1
View File
@@ -7,7 +7,7 @@
{
"kind": 2,
"language": "github-issues",
"value": "$REPOS=repo:microsoft/vscode repo:microsoft/vscode-remote-release repo:microsoft/vscode-copilot repo:microsoft/vscode-copilot-release repo:microsoft/vscode-js-debug repo:microsoft/vscode-pull-request-github repo:microsoft/vscode-github-issue-notebooks repo:microsoft/vscode-internalbacklog repo:microsoft/vscode-dev repo:microsoft/vscode-unpkg repo:microsoft/vscode-references-view repo:microsoft/vscode-anycode repo:microsoft/vscode-hexeditor repo:microsoft/vscode-extension-telemetry repo:microsoft/vscode-livepreview repo:microsoft/vscode-remotehub repo:microsoft/vscode-settings-sync-server repo:microsoft/vscode-remote-repositories-github repo:microsoft/monaco-editor repo:microsoft/vscode-vsce repo:microsoft/vscode-dev-chrome-launcher repo:microsoft/vscode-emmet-helper repo:microsoft/vscode-livepreview repo:microsoft/vscode-livepreview repo:microsoft/vscode-python repo:microsoft/vscode-python-debugger repo:microsoft/vscode-jupyter repo:microsoft/vscode-jupyter-internal repo:microsoft/vscode-github-issue-notebooks repo:microsoft/vscode-l10n repo:microsoft/vscode-remote-tunnels repo:microsoft/vscode-pylint repo:microsoft/vscode-black-formatter repo:microsoft/vscode-isort repo:microsoft/lsprotocol repo:microsoft/vscode-flake8 repo:microsoft/vscode-autopep8 repo:microsoft/vscode-python-tools-extension-template repo:microsoft/vscode-mypy repo:microsoft/vscode-python-debugger\n\n$MILESTONE=milestone:\"October 2023\"\n\n$MINE=assignee:@me\n"
"value": "$REPOS=repo:microsoft/vscode repo:microsoft/vscode-remote-release repo:microsoft/vscode-copilot repo:microsoft/vscode-copilot-release repo:microsoft/vscode-js-debug repo:microsoft/vscode-pull-request-github repo:microsoft/vscode-github-issue-notebooks repo:microsoft/vscode-internalbacklog repo:microsoft/vscode-dev repo:microsoft/vscode-unpkg repo:microsoft/vscode-references-view repo:microsoft/vscode-anycode repo:microsoft/vscode-hexeditor repo:microsoft/vscode-extension-telemetry repo:microsoft/vscode-livepreview repo:microsoft/vscode-remotehub repo:microsoft/vscode-settings-sync-server repo:microsoft/vscode-remote-repositories-github repo:microsoft/monaco-editor repo:microsoft/vscode-vsce repo:microsoft/vscode-dev-chrome-launcher repo:microsoft/vscode-emmet-helper repo:microsoft/vscode-livepreview repo:microsoft/vscode-livepreview repo:microsoft/vscode-python repo:microsoft/vscode-python-debugger repo:microsoft/vscode-jupyter repo:microsoft/vscode-jupyter-internal repo:microsoft/vscode-github-issue-notebooks repo:microsoft/vscode-l10n repo:microsoft/vscode-remote-tunnels repo:microsoft/vscode-pylint repo:microsoft/vscode-black-formatter repo:microsoft/vscode-isort repo:microsoft/lsprotocol repo:microsoft/vscode-flake8 repo:microsoft/vscode-autopep8 repo:microsoft/vscode-python-tools-extension-template repo:microsoft/vscode-mypy repo:microsoft/vscode-python-debugger\n\n$MILESTONE=milestone:\"November 2023\"\n\n$MINE=assignee:@me\n"
},
{
"kind": 1,
+1 -1
View File
@@ -7,7 +7,7 @@
{
"kind": 2,
"language": "github-issues",
"value": "// list of repos we work in\n$repos=repo:microsoft/vscode repo:microsoft/vscode-remote-release repo:microsoft/vscode-js-debug repo:microsoft/vscode-pull-request-github repo:microsoft/vscode-github-issue-notebooks repo:microsoft/vscode-internalbacklog repo:microsoft/vscode-dev repo:microsoft/vscode-unpkg repo:microsoft/vscode-references-view repo:microsoft/vscode-anycode repo:microsoft/vscode-hexeditor repo:microsoft/vscode-extension-telemetry repo:microsoft/vscode-livepreview repo:microsoft/vscode-remotehub repo:microsoft/vscode-settings-sync-server repo:microsoft/vscode-remote-repositories-github repo:microsoft/monaco-editor repo:microsoft/vscode-vsce repo:microsoft/vscode-dev-chrome-launcher repo:microsoft/vscode-emmet-helper repo:microsoft/vscode-python repo:microsoft/vscode-jupyter repo:microsoft/vscode-jupyter-internal repo:microsoft/vscode-github-issue-notebooks repo:microsoft/vscode-l10n repo:microsoft/vscode-remote-tunnels repo:microsoft/vscode-markdown-tm-grammar repo:microsoft/vscode-markdown-languageservice repo:microsoft/vscode-copilot repo:microsoft/vscode-copilot-release\n\n// current milestone name\n$milestone=milestone:\"October 2023\"\n"
"value": "// list of repos we work in\n$repos=repo:microsoft/vscode repo:microsoft/vscode-remote-release repo:microsoft/vscode-js-debug repo:microsoft/vscode-pull-request-github repo:microsoft/vscode-github-issue-notebooks repo:microsoft/vscode-internalbacklog repo:microsoft/vscode-dev repo:microsoft/vscode-unpkg repo:microsoft/vscode-references-view repo:microsoft/vscode-anycode repo:microsoft/vscode-hexeditor repo:microsoft/vscode-extension-telemetry repo:microsoft/vscode-livepreview repo:microsoft/vscode-remotehub repo:microsoft/vscode-settings-sync-server repo:microsoft/vscode-remote-repositories-github repo:microsoft/monaco-editor repo:microsoft/vscode-vsce repo:microsoft/vscode-dev-chrome-launcher repo:microsoft/vscode-emmet-helper repo:microsoft/vscode-python repo:microsoft/vscode-jupyter repo:microsoft/vscode-jupyter-internal repo:microsoft/vscode-github-issue-notebooks repo:microsoft/vscode-l10n repo:microsoft/vscode-remote-tunnels repo:microsoft/vscode-markdown-tm-grammar repo:microsoft/vscode-markdown-languageservice repo:microsoft/vscode-copilot repo:microsoft/vscode-copilot-release\n\n// current milestone name\n$milestone=milestone:\"November 2023\"\n"
},
{
"kind": 1,
+1 -1
View File
@@ -12,7 +12,7 @@
{
"kind": 2,
"language": "github-issues",
"value": "$repos=repo:microsoft/vscode repo:microsoft/vscode-remote-release repo:microsoft/vscode-js-debug repo:microsoft/vscode-pull-request-github repo:microsoft/vscode-github-issue-notebooks repo:microsoft/vscode-internalbacklog repo:microsoft/vscode-dev repo:microsoft/vscode-unpkg repo:microsoft/vscode-references-view repo:microsoft/vscode-anycode repo:microsoft/vscode-hexeditor repo:microsoft/vscode-extension-telemetry repo:microsoft/vscode-livepreview repo:microsoft/vscode-remotehub repo:microsoft/vscode-settings-sync-server repo:microsoft/vscode-remote-repositories-github repo:microsoft/monaco-editor repo:microsoft/vscode-vsce repo:microsoft/vscode-dev-chrome-launcher repo:microsoft/vscode-emmet-helper repo:microsoft/vscode-livepreview repo:microsoft/vscode-livepreview repo:microsoft/vscode-python repo:microsoft/vscode-jupyter repo:microsoft/vscode-jupyter-internal repo:microsoft/vscode-github-issue-notebooks repo:microsoft/vscode-l10n repo:microsoft/vscode-remote-tunnels\n$milestone=milestone:\"October 2023\"\n$closedRecently=closed:>2023-09-29\n"
"value": "$repos=repo:microsoft/vscode repo:microsoft/vscode-remote-release repo:microsoft/vscode-js-debug repo:microsoft/vscode-pull-request-github repo:microsoft/vscode-github-issue-notebooks repo:microsoft/vscode-internalbacklog repo:microsoft/vscode-dev repo:microsoft/vscode-unpkg repo:microsoft/vscode-references-view repo:microsoft/vscode-anycode repo:microsoft/vscode-hexeditor repo:microsoft/vscode-extension-telemetry repo:microsoft/vscode-livepreview repo:microsoft/vscode-remotehub repo:microsoft/vscode-settings-sync-server repo:microsoft/vscode-remote-repositories-github repo:microsoft/monaco-editor repo:microsoft/vscode-vsce repo:microsoft/vscode-dev-chrome-launcher repo:microsoft/vscode-emmet-helper repo:microsoft/vscode-livepreview repo:microsoft/vscode-livepreview repo:microsoft/vscode-python repo:microsoft/vscode-jupyter repo:microsoft/vscode-jupyter-internal repo:microsoft/vscode-github-issue-notebooks repo:microsoft/vscode-l10n repo:microsoft/vscode-remote-tunnels\n$milestone=milestone:\"November 2023\"\n$closedRecently=closed:>2023-09-29\n"
},
{
"kind": 1,
+1 -1
View File
@@ -2,7 +2,7 @@
{
"kind": 2,
"language": "github-issues",
"value": "$milestone=milestone:\"October 2023\"\n"
"value": "$milestone=milestone:\"November 2023\"\n"
},
{
"kind": 1,
@@ -1,7 +1,7 @@
{
"name": "vscode-markdown-languageserver",
"description": "Markdown language server",
"version": "0.4.0-alpha.7",
"version": "0.4.0-alpha.8",
"author": "Microsoft Corporation",
"license": "MIT",
"engines": {
@@ -18,7 +18,7 @@
"vscode-languageserver": "^8.1.0",
"vscode-languageserver-textdocument": "^1.0.8",
"vscode-languageserver-types": "^3.17.3",
"vscode-markdown-languageservice": "^0.4.0-alpha.7",
"vscode-markdown-languageservice": "^0.4.0-alpha.8",
"vscode-uri": "^3.0.7"
},
"devDependencies": {
@@ -128,10 +128,10 @@ vscode-languageserver@^8.1.0:
dependencies:
vscode-languageserver-protocol "3.17.3"
vscode-markdown-languageservice@^0.4.0-alpha.7:
version "0.4.0-alpha.7"
resolved "https://registry.yarnpkg.com/vscode-markdown-languageservice/-/vscode-markdown-languageservice-0.4.0-alpha.7.tgz#485e3394ff792a6fb225e5323ba9b5170f6fa7e7"
integrity sha512-GZ8e1ewU989nLSRyQp3wXjIBFWZnu/rfo4gJxazujU2nTkR+VhPGh/ar/5pX7iHLRbESvcqgVqRQNU7zzVo/hw==
vscode-markdown-languageservice@^0.4.0-alpha.8:
version "0.4.0-alpha.8"
resolved "https://registry.yarnpkg.com/vscode-markdown-languageservice/-/vscode-markdown-languageservice-0.4.0-alpha.8.tgz#5c3aaf3b3cd3f6b309f8dfcf93cbfb1397041adc"
integrity sha512-6S6RE5s+4biWg2xk9bpwNi6GihUYQIVxdO3I+jb/XDyvfmqYVxrN86cKLF8QSbaQvX3fMuBAxBLFfX93FdJi3w==
dependencies:
"@vscode/l10n" "^0.0.10"
node-html-parser "^6.1.5"
@@ -27,7 +27,7 @@ export function inferredProjectCompilerOptions(
): Proto.ExternalProjectCompilerOptions {
const projectConfig: Proto.ExternalProjectCompilerOptions = {
module: 'ESNext' as Proto.ModuleKind,
moduleResolution: (version.gte(API.v500) ? 'Bundler' : 'Node') as Proto.ModuleResolutionKind,
moduleResolution: 'Node' as Proto.ModuleResolutionKind,
target: 'ES2022' as Proto.ScriptTarget,
jsx: 'react' as Proto.JsxEmit,
};
+7 -7
View File
@@ -96,14 +96,14 @@
"vscode-oniguruma": "1.7.0",
"vscode-regexpp": "^3.1.0",
"vscode-textmate": "9.0.0",
"xterm": "5.4.0-beta.32",
"xterm-addon-canvas": "0.6.0-beta.32",
"xterm": "5.4.0-beta.37",
"xterm-addon-canvas": "0.6.0-beta.37",
"xterm-addon-image": "0.6.0-beta.21",
"xterm-addon-search": "0.14.0-beta.31",
"xterm-addon-serialize": "0.12.0-beta.31",
"xterm-addon-unicode11": "0.7.0-beta.31",
"xterm-addon-webgl": "0.17.0-beta.31",
"xterm-headless": "5.4.0-beta.32",
"xterm-addon-search": "0.14.0-beta.36",
"xterm-addon-serialize": "0.12.0-beta.36",
"xterm-addon-unicode11": "0.7.0-beta.36",
"xterm-addon-webgl": "0.17.0-beta.36",
"xterm-headless": "5.4.0-beta.37",
"yauzl": "^2.9.2",
"yazl": "^2.4.3"
},
+7 -7
View File
@@ -26,14 +26,14 @@
"vscode-oniguruma": "1.7.0",
"vscode-regexpp": "^3.1.0",
"vscode-textmate": "9.0.0",
"xterm": "5.4.0-beta.32",
"xterm-addon-canvas": "0.6.0-beta.32",
"xterm": "5.4.0-beta.37",
"xterm-addon-canvas": "0.6.0-beta.37",
"xterm-addon-image": "0.6.0-beta.21",
"xterm-addon-search": "0.14.0-beta.31",
"xterm-addon-serialize": "0.12.0-beta.31",
"xterm-addon-unicode11": "0.7.0-beta.31",
"xterm-addon-webgl": "0.17.0-beta.31",
"xterm-headless": "5.4.0-beta.32",
"xterm-addon-search": "0.14.0-beta.36",
"xterm-addon-serialize": "0.12.0-beta.36",
"xterm-addon-unicode11": "0.7.0-beta.36",
"xterm-addon-webgl": "0.17.0-beta.36",
"xterm-headless": "5.4.0-beta.37",
"yauzl": "^2.9.2",
"yazl": "^2.4.3"
}
+5 -5
View File
@@ -11,11 +11,11 @@
"tas-client-umd": "0.1.8",
"vscode-oniguruma": "1.7.0",
"vscode-textmate": "9.0.0",
"xterm": "5.4.0-beta.32",
"xterm-addon-canvas": "0.6.0-beta.32",
"xterm": "5.4.0-beta.37",
"xterm-addon-canvas": "0.6.0-beta.37",
"xterm-addon-image": "0.6.0-beta.21",
"xterm-addon-search": "0.14.0-beta.31",
"xterm-addon-unicode11": "0.7.0-beta.31",
"xterm-addon-webgl": "0.17.0-beta.31"
"xterm-addon-search": "0.14.0-beta.36",
"xterm-addon-unicode11": "0.7.0-beta.36",
"xterm-addon-webgl": "0.17.0-beta.36"
}
}
+20 -20
View File
@@ -68,32 +68,32 @@ vscode-textmate@9.0.0:
resolved "https://registry.yarnpkg.com/vscode-textmate/-/vscode-textmate-9.0.0.tgz#313c6c8792b0507aef35aeb81b6b370b37c44d6c"
integrity sha512-Cl65diFGxz7gpwbav10HqiY/eVYTO1sjQpmRmV991Bj7wAoOAjGQ97PpQcXorDE2Uc4hnGWLY17xme+5t6MlSg==
xterm-addon-canvas@0.6.0-beta.32:
version "0.6.0-beta.32"
resolved "https://registry.yarnpkg.com/xterm-addon-canvas/-/xterm-addon-canvas-0.6.0-beta.32.tgz#c9e74dd72fcc981a2e0cbd0b82827676bc5c74b9"
integrity sha512-Xw7oE4dbS+x+pu6cGW1bDSXcVviuorLz1OLaYw46jjmDezIqQIIEMhSMOprExFEWgeRQ9AEN4lPqw6aH87V74w==
xterm-addon-canvas@0.6.0-beta.37:
version "0.6.0-beta.37"
resolved "https://registry.yarnpkg.com/xterm-addon-canvas/-/xterm-addon-canvas-0.6.0-beta.37.tgz#4f7692fc87f3500a5a6e7f822ec74796e6a36db2"
integrity sha512-eFN7iPxqiQosUO+rbXKwPz/AR3TLJcLCVWjvT5EaewqNpw+E9rWVwRRPGqYSw+qkSKM/vcNlySIkq4hmpA/ohg==
xterm-addon-image@0.6.0-beta.21:
version "0.6.0-beta.21"
resolved "https://registry.yarnpkg.com/xterm-addon-image/-/xterm-addon-image-0.6.0-beta.21.tgz#e3708bc504c56a23ff31f12a2eeb335331a92aac"
integrity sha512-8/PTaXVPa4kQ0xzVeuZZk10OpbZBj2cgfwhM2B0ChSPvwrk0lX+ksnXdtDKH3tg+JYvo7fIhNXtkr4NwWt7VJQ==
xterm-addon-search@0.14.0-beta.31:
version "0.14.0-beta.31"
resolved "https://registry.yarnpkg.com/xterm-addon-search/-/xterm-addon-search-0.14.0-beta.31.tgz#933ca5d2d642dacad29f2cfbd50830cff83bc274"
integrity sha512-JRY1ukhoh32D0AMz78xpumQkLgkcP9d3GXj6gzVHZZsjLAMDaJYEubYq1bUhM7IGHUyg+x0sdRJyx7d6fJpiQg==
xterm-addon-search@0.14.0-beta.36:
version "0.14.0-beta.36"
resolved "https://registry.yarnpkg.com/xterm-addon-search/-/xterm-addon-search-0.14.0-beta.36.tgz#4bb161130c39090d506f73468ef65054aedcb9f0"
integrity sha512-2ydZV1Nt8d0vOjZ/y2RXiw3QLgabK+PCA7yETqZNivnmhSfcxtYPyI4aRfG/lc3hoMKiPppSSjJF0MlV/qo8ww==
xterm-addon-unicode11@0.7.0-beta.31:
version "0.7.0-beta.31"
resolved "https://registry.yarnpkg.com/xterm-addon-unicode11/-/xterm-addon-unicode11-0.7.0-beta.31.tgz#abcba752172323f31312bd8a3f9b6a049dbca6e3"
integrity sha512-vvBKJbBoLbeIf2++6D16VnOOwevZE3nyO/PDZ7cyTJK1eYR73rr8ZbjUrH92YoTu4Z8MpZFepGQOgK/vlAQMwQ==
xterm-addon-unicode11@0.7.0-beta.36:
version "0.7.0-beta.36"
resolved "https://registry.yarnpkg.com/xterm-addon-unicode11/-/xterm-addon-unicode11-0.7.0-beta.36.tgz#bde0b8c98211b74b0288cd5bad09107384b870ca"
integrity sha512-vV/f7dTP/46JjoJLYDCxolCWPoUn0cF7S5upYvY0ZA1VLQ9UnXmaNjzrg+9f+QBoXEQ2eQDLQcRFWOc6BAbF+A==
xterm-addon-webgl@0.17.0-beta.31:
version "0.17.0-beta.31"
resolved "https://registry.yarnpkg.com/xterm-addon-webgl/-/xterm-addon-webgl-0.17.0-beta.31.tgz#3cd29b4858e3f4f6dd5a8dd969454e85e1f43baa"
integrity sha512-vYHj+HlTcqUlFFVuoCTjlgh89/lIoSkZ7Nc87cwSFTrJsl07qoKutmpupqFXyjhbEA1fQY2SuQLx08Gmf2jWkQ==
xterm-addon-webgl@0.17.0-beta.36:
version "0.17.0-beta.36"
resolved "https://registry.yarnpkg.com/xterm-addon-webgl/-/xterm-addon-webgl-0.17.0-beta.36.tgz#6ed16a83cd4bed3cbddd631e7974375aa8f7e023"
integrity sha512-5PNQZcNH2UTaqSf7Exgh/fvsNeTOs+CSEuIaTafzKuMIrWH14+cRdyJdzyo8OKTNzhJOjwWDOTQTD/sur4lrLg==
xterm@5.4.0-beta.32:
version "5.4.0-beta.32"
resolved "https://registry.yarnpkg.com/xterm/-/xterm-5.4.0-beta.32.tgz#1b4242cf1c0c1a5a1070da58d3f11956b537130a"
integrity sha512-mWTwEiNBFMF89oqVfi6qTM2Py5gC1Mwvslx1KxmI2Ukgh9v3CrqKDhj29eY1ZeAo0uuYknFWKyuexqp+3SHJCA==
xterm@5.4.0-beta.37:
version "5.4.0-beta.37"
resolved "https://registry.yarnpkg.com/xterm/-/xterm-5.4.0-beta.37.tgz#bae127be8c939f096232d9858e77a457d6b77ddf"
integrity sha512-ys+mXqLFrJc7khmYN/MgBnfLv38NgXfkwkEXsCZKHGqn3h2xUBvTvsrSEWO3NQeDPLj4zMr1RwqTblMK9St3BA==
+28 -28
View File
@@ -589,45 +589,45 @@ wrappy@1:
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=
xterm-addon-canvas@0.6.0-beta.32:
version "0.6.0-beta.32"
resolved "https://registry.yarnpkg.com/xterm-addon-canvas/-/xterm-addon-canvas-0.6.0-beta.32.tgz#c9e74dd72fcc981a2e0cbd0b82827676bc5c74b9"
integrity sha512-Xw7oE4dbS+x+pu6cGW1bDSXcVviuorLz1OLaYw46jjmDezIqQIIEMhSMOprExFEWgeRQ9AEN4lPqw6aH87V74w==
xterm-addon-canvas@0.6.0-beta.37:
version "0.6.0-beta.37"
resolved "https://registry.yarnpkg.com/xterm-addon-canvas/-/xterm-addon-canvas-0.6.0-beta.37.tgz#4f7692fc87f3500a5a6e7f822ec74796e6a36db2"
integrity sha512-eFN7iPxqiQosUO+rbXKwPz/AR3TLJcLCVWjvT5EaewqNpw+E9rWVwRRPGqYSw+qkSKM/vcNlySIkq4hmpA/ohg==
xterm-addon-image@0.6.0-beta.21:
version "0.6.0-beta.21"
resolved "https://registry.yarnpkg.com/xterm-addon-image/-/xterm-addon-image-0.6.0-beta.21.tgz#e3708bc504c56a23ff31f12a2eeb335331a92aac"
integrity sha512-8/PTaXVPa4kQ0xzVeuZZk10OpbZBj2cgfwhM2B0ChSPvwrk0lX+ksnXdtDKH3tg+JYvo7fIhNXtkr4NwWt7VJQ==
xterm-addon-search@0.14.0-beta.31:
version "0.14.0-beta.31"
resolved "https://registry.yarnpkg.com/xterm-addon-search/-/xterm-addon-search-0.14.0-beta.31.tgz#933ca5d2d642dacad29f2cfbd50830cff83bc274"
integrity sha512-JRY1ukhoh32D0AMz78xpumQkLgkcP9d3GXj6gzVHZZsjLAMDaJYEubYq1bUhM7IGHUyg+x0sdRJyx7d6fJpiQg==
xterm-addon-search@0.14.0-beta.36:
version "0.14.0-beta.36"
resolved "https://registry.yarnpkg.com/xterm-addon-search/-/xterm-addon-search-0.14.0-beta.36.tgz#4bb161130c39090d506f73468ef65054aedcb9f0"
integrity sha512-2ydZV1Nt8d0vOjZ/y2RXiw3QLgabK+PCA7yETqZNivnmhSfcxtYPyI4aRfG/lc3hoMKiPppSSjJF0MlV/qo8ww==
xterm-addon-serialize@0.12.0-beta.31:
version "0.12.0-beta.31"
resolved "https://registry.yarnpkg.com/xterm-addon-serialize/-/xterm-addon-serialize-0.12.0-beta.31.tgz#2a95dc1e12f4097e2894b04c9cb8fff0bc0b858c"
integrity sha512-h2rWR+Lfi1Iv4VkLUlrBMYh5Mdq8vux2BKyCJe6a1ZnEu5Dzb0VuiNxfTKXTCT5M83nMn7TCB9TX0E8z6bs7xw==
xterm-addon-serialize@0.12.0-beta.36:
version "0.12.0-beta.36"
resolved "https://registry.yarnpkg.com/xterm-addon-serialize/-/xterm-addon-serialize-0.12.0-beta.36.tgz#8e74159317e2c1e5f2724fd92b85df2b87d2c9c9"
integrity sha512-J2mr3Wuxzvxke14IpfJBhwCHlWoB428FE06tOfbGi5lCBm0AnO2cIyRymvgVZG4QVXVxzzWroE8wP/WQQVe45w==
xterm-addon-unicode11@0.7.0-beta.31:
version "0.7.0-beta.31"
resolved "https://registry.yarnpkg.com/xterm-addon-unicode11/-/xterm-addon-unicode11-0.7.0-beta.31.tgz#abcba752172323f31312bd8a3f9b6a049dbca6e3"
integrity sha512-vvBKJbBoLbeIf2++6D16VnOOwevZE3nyO/PDZ7cyTJK1eYR73rr8ZbjUrH92YoTu4Z8MpZFepGQOgK/vlAQMwQ==
xterm-addon-unicode11@0.7.0-beta.36:
version "0.7.0-beta.36"
resolved "https://registry.yarnpkg.com/xterm-addon-unicode11/-/xterm-addon-unicode11-0.7.0-beta.36.tgz#bde0b8c98211b74b0288cd5bad09107384b870ca"
integrity sha512-vV/f7dTP/46JjoJLYDCxolCWPoUn0cF7S5upYvY0ZA1VLQ9UnXmaNjzrg+9f+QBoXEQ2eQDLQcRFWOc6BAbF+A==
xterm-addon-webgl@0.17.0-beta.31:
version "0.17.0-beta.31"
resolved "https://registry.yarnpkg.com/xterm-addon-webgl/-/xterm-addon-webgl-0.17.0-beta.31.tgz#3cd29b4858e3f4f6dd5a8dd969454e85e1f43baa"
integrity sha512-vYHj+HlTcqUlFFVuoCTjlgh89/lIoSkZ7Nc87cwSFTrJsl07qoKutmpupqFXyjhbEA1fQY2SuQLx08Gmf2jWkQ==
xterm-addon-webgl@0.17.0-beta.36:
version "0.17.0-beta.36"
resolved "https://registry.yarnpkg.com/xterm-addon-webgl/-/xterm-addon-webgl-0.17.0-beta.36.tgz#6ed16a83cd4bed3cbddd631e7974375aa8f7e023"
integrity sha512-5PNQZcNH2UTaqSf7Exgh/fvsNeTOs+CSEuIaTafzKuMIrWH14+cRdyJdzyo8OKTNzhJOjwWDOTQTD/sur4lrLg==
xterm-headless@5.4.0-beta.32:
version "5.4.0-beta.32"
resolved "https://registry.yarnpkg.com/xterm-headless/-/xterm-headless-5.4.0-beta.32.tgz#0d5cd35e1a0372888055ff0b06dfe17457979a6c"
integrity sha512-DQduq8KSoQZyRrQAFB+FkcY2UMxCW39P1/duOpksebc6PT9pbGkyPe5s+AdUQGiYzriEpzVtKUzDcquoVmpPhA==
xterm-headless@5.4.0-beta.37:
version "5.4.0-beta.37"
resolved "https://registry.yarnpkg.com/xterm-headless/-/xterm-headless-5.4.0-beta.37.tgz#1e89dfa7e667a5951974a9e9b5e1b0875198ca65"
integrity sha512-iP28Z419p7anaNetLhmPOpt/DUdeA45jVLqoTn8bRpwFj8kM/gI76tUO9y/TyMfv79yWwPv2MrkALfS6ZyTi7g==
xterm@5.4.0-beta.32:
version "5.4.0-beta.32"
resolved "https://registry.yarnpkg.com/xterm/-/xterm-5.4.0-beta.32.tgz#1b4242cf1c0c1a5a1070da58d3f11956b537130a"
integrity sha512-mWTwEiNBFMF89oqVfi6qTM2Py5gC1Mwvslx1KxmI2Ukgh9v3CrqKDhj29eY1ZeAo0uuYknFWKyuexqp+3SHJCA==
xterm@5.4.0-beta.37:
version "5.4.0-beta.37"
resolved "https://registry.yarnpkg.com/xterm/-/xterm-5.4.0-beta.37.tgz#bae127be8c939f096232d9858e77a457d6b77ddf"
integrity sha512-ys+mXqLFrJc7khmYN/MgBnfLv38NgXfkwkEXsCZKHGqn3h2xUBvTvsrSEWO3NQeDPLj4zMr1RwqTblMK9St3BA==
yallist@^4.0.0:
version "4.0.0"
+52 -46
View File
@@ -18,23 +18,38 @@ import * as platform from 'vs/base/common/platform';
import { URI } from 'vs/base/common/uri';
import { hash } from 'vs/base/common/hash';
type WindowGlobal = Window & typeof globalThis;
interface IWindow {
readonly window: WindowGlobal;
readonly disposables: DisposableStore;
}
export const { registerWindow, getWindows, getWindowsCount, onDidRegisterWindow, onWillUnregisterWindow, onDidUnregisterWindow } = (function () {
const windows = new Set([window]);
const onDidRegisterWindow = new event.Emitter<{ window: Window & typeof globalThis; disposables: DisposableStore }>();
const onDidUnregisterWindow = new event.Emitter<Window & typeof globalThis>();
const onWillUnregisterWindow = new event.Emitter<Window & typeof globalThis>();
const windows = new Map<WindowGlobal, IWindow>();
windows.set(window, { window, disposables: new DisposableStore() });
const onDidRegisterWindow = new event.Emitter<IWindow>();
const onDidUnregisterWindow = new event.Emitter<WindowGlobal>();
const onWillUnregisterWindow = new event.Emitter<WindowGlobal>();
return {
onDidRegisterWindow: onDidRegisterWindow.event,
onWillUnregisterWindow: onWillUnregisterWindow.event,
onDidUnregisterWindow: onDidUnregisterWindow.event,
registerWindow(window: Window & typeof globalThis): IDisposable {
registerWindow(window: WindowGlobal): IDisposable {
if (windows.has(window)) {
return Disposable.None;
}
windows.add(window);
const disposables = new DisposableStore();
const registeredWindow = {
window,
disposables: disposables.add(new DisposableStore())
};
windows.set(window, registeredWindow);
disposables.add(toDisposable(() => {
windows.delete(window);
onDidUnregisterWindow.fire(window);
@@ -44,14 +59,12 @@ export const { registerWindow, getWindows, getWindowsCount, onDidRegisterWindow,
onWillUnregisterWindow.fire(window);
}));
const eventDisposables = new DisposableStore();
disposables.add(eventDisposables);
onDidRegisterWindow.fire({ window, disposables: eventDisposables });
onDidRegisterWindow.fire(registeredWindow);
return disposables;
},
getWindows(): Iterable<Window & typeof globalThis> {
return windows;
getWindows(): Iterable<IWindow> {
return windows.values();
},
getWindowsCount(): number {
return windows.size;
@@ -163,14 +176,14 @@ export function addDisposableGenericMouseUpListener(node: EventTarget, handler:
* If currently in an animation frame, `runner` will be executed immediately.
* @return token that can be used to cancel the scheduled runner (only if `runner` was not executed immediately).
*/
export let runAtThisOrScheduleAtNextAnimationFrame: (runner: () => void, priority?: number) => IDisposable;
export let runAtThisOrScheduleAtNextAnimationFrame: (runner: () => void, targetWindow: Window, priority?: number) => IDisposable;
/**
* Schedule a callback to be run at the next animation frame.
* This allows multiple parties to register callbacks that should run at the next animation frame.
* If currently in an animation frame, `runner` will be executed at the next animation frame.
* @return token that can be used to cancel the scheduled runner.
*/
export let scheduleAtNextAnimationFrame: (runner: () => void, priority?: number) => IDisposable;
export let scheduleAtNextAnimationFrame: (runner: () => void, targetWindow: Window, priority?: number) => IDisposable;
class AnimationFrameQueueItem implements IDisposable {
@@ -239,35 +252,35 @@ class AnimationFrameQueueItem implements IDisposable {
inAnimationFrameRunner = false;
};
scheduleAtNextAnimationFrame = (runner: () => void, priority: number = 0) => {
scheduleAtNextAnimationFrame = (runner: () => void, targetWindow: Window, priority: number = 0) => {
const item = new AnimationFrameQueueItem(runner, priority);
NEXT_QUEUE.push(item);
if (!animFrameRequested) {
animFrameRequested = true;
requestAnimationFrame(animationFrameRunner);
targetWindow.requestAnimationFrame(animationFrameRunner);
}
return item;
};
runAtThisOrScheduleAtNextAnimationFrame = (runner: () => void, priority?: number) => {
runAtThisOrScheduleAtNextAnimationFrame = (runner: () => void, targetWindow: Window, priority?: number) => {
if (inAnimationFrameRunner) {
const item = new AnimationFrameQueueItem(runner, priority);
CURRENT_QUEUE!.push(item);
return item;
} else {
return scheduleAtNextAnimationFrame(runner, priority);
return scheduleAtNextAnimationFrame(runner, targetWindow, priority);
}
};
})();
export function measure(callback: () => void): IDisposable {
return scheduleAtNextAnimationFrame(callback, 10000 /* must be early */);
export function measure(callback: () => void, targetWindow: Window): IDisposable {
return scheduleAtNextAnimationFrame(callback, targetWindow, 10000 /* must be early */);
}
export function modify(callback: () => void): IDisposable {
return scheduleAtNextAnimationFrame(callback, -10000 /* must be late */);
export function modify(callback: () => void, targetWindow: Window): IDisposable {
return scheduleAtNextAnimationFrame(callback, targetWindow, -10000 /* must be late */);
}
/**
@@ -758,25 +771,24 @@ export function getActiveDocument(): Document {
return document;
}
const documents = Array.from(getWindows()).map(window => window.document);
return documents.find(doc => doc.hasFocus()) ?? document;
const documents = Array.from(getWindows()).map(({ window }) => window.document);
return documents.find(document => document.hasFocus()) ?? document;
}
export function getActiveWindow(): Window & typeof globalThis {
export function getActiveWindow(): WindowGlobal {
const document = getActiveDocument();
return document.defaultView?.window ?? window;
}
export function getWindow(element: Node): Window & typeof globalThis;
export function getWindow(event: UIEvent): Window & typeof globalThis;
export function getWindow(obj: unknown): Window & typeof globalThis;
export function getWindow(e: unknown): Window & typeof globalThis {
const candidateNode = e as Node | undefined;
export function getWindow(element: Node | undefined | null): WindowGlobal;
export function getWindow(event: UIEvent | undefined | null): WindowGlobal;
export function getWindow(e: unknown): WindowGlobal {
const candidateNode = e as Node | undefined | null;
if (candidateNode?.ownerDocument?.defaultView) {
return candidateNode.ownerDocument.defaultView.window;
}
const candidateEvent = e as UIEvent | undefined;
const candidateEvent = e as UIEvent | undefined | null;
if (candidateEvent?.view) {
return candidateEvent.view.window;
}
@@ -805,19 +817,13 @@ export function createStyleSheet(container: HTMLElement = document.head, beforeA
// With <head> as container, the stylesheet becomes global and is tracked
// to support auxiliary windows to clone the stylesheet.
if (container === document.head) {
for (const targetWindow of getWindows()) {
for (const { window: targetWindow, disposables } of getWindows()) {
if (targetWindow === window) {
continue; // main window is already tracked
}
const cloneDisposable = cloneGlobalStyleSheet(style, targetWindow);
const cloneDisposable = disposables.add(cloneGlobalStyleSheet(style, targetWindow));
disposableStore?.add(cloneDisposable);
disposableStore?.add(event.Event.once(onDidUnregisterWindow)(unregisteredWindow => {
if (unregisteredWindow === targetWindow) {
cloneDisposable.dispose();
}
}));
}
}
@@ -989,22 +995,22 @@ function isCSSStyleRule(rule: CSSRule): rule is CSSStyleRule {
export function isMouseEvent(e: unknown): e is MouseEvent {
// eslint-disable-next-line no-restricted-syntax
return e instanceof MouseEvent || e instanceof getWindow(e).MouseEvent;
return e instanceof MouseEvent || e instanceof getWindow(e as UIEvent).MouseEvent;
}
export function isKeyboardEvent(e: unknown): e is KeyboardEvent {
// eslint-disable-next-line no-restricted-syntax
return e instanceof KeyboardEvent || e instanceof getWindow(e).KeyboardEvent;
return e instanceof KeyboardEvent || e instanceof getWindow(e as UIEvent).KeyboardEvent;
}
export function isPointerEvent(e: unknown): e is PointerEvent {
// eslint-disable-next-line no-restricted-syntax
return e instanceof PointerEvent || e instanceof getWindow(e).PointerEvent;
return e instanceof PointerEvent || e instanceof getWindow(e as UIEvent).PointerEvent;
}
export function isDragEvent(e: unknown): e is DragEvent {
// eslint-disable-next-line no-restricted-syntax
return e instanceof DragEvent || e instanceof getWindow(e).DragEvent;
return e instanceof DragEvent || e instanceof getWindow(e as UIEvent).DragEvent;
}
export const EventType = {
@@ -1456,13 +1462,13 @@ export function windowOpenWithSuccess(url: string, noOpener = true): boolean {
return false;
}
export function animate(fn: () => void): IDisposable {
export function animate(fn: () => void, targetWindow: Window): IDisposable {
const step = () => {
fn();
stepDisposable = scheduleAtNextAnimationFrame(step);
stepDisposable = scheduleAtNextAnimationFrame(step, targetWindow);
};
let stepDisposable = scheduleAtNextAnimationFrame(step);
let stepDisposable = scheduleAtNextAnimationFrame(step, targetWindow);
return toDisposable(() => stepDisposable.dispose());
}
+12 -12
View File
@@ -93,7 +93,7 @@ export class Gesture extends Disposable {
this._register(EventUtils.runAndSubscribe(DomUtils.onDidRegisterWindow, ({ window, disposables }) => {
disposables.add(DomUtils.addDisposableListener(window.document, 'touchstart', (e: TouchEvent) => this.onTouchStart(e), { passive: false }));
disposables.add(DomUtils.addDisposableListener(window.document, 'touchend', (e: TouchEvent) => this.onTouchEnd(e)));
disposables.add(DomUtils.addDisposableListener(window.document, 'touchend', (e: TouchEvent) => this.onTouchEnd(window, e)));
disposables.add(DomUtils.addDisposableListener(window.document, 'touchmove', (e: TouchEvent) => this.onTouchMove(e), { passive: false }));
}, { window, disposables: this._store }));
}
@@ -173,7 +173,7 @@ export class Gesture extends Disposable {
}
}
private onTouchEnd(e: TouchEvent): void {
private onTouchEnd(targetWindow: Window, e: TouchEvent): void {
const timestamp = Date.now(); // use Date.now() because on FF e.timeStamp is not epoch based.
const activeTouchCount = Object.keys(this.activeTouches).length;
@@ -218,13 +218,13 @@ export class Gesture extends Disposable {
// We need to get all the dispatch targets on the start of the inertia event
const dispatchTo = [...this.targets].filter(t => data.initialTarget instanceof Node && t.contains(data.initialTarget));
this.inertia(dispatchTo, timestamp, // time now
Math.abs(deltaX) / deltaT, // speed
deltaX > 0 ? 1 : -1, // x direction
finalX, // x now
Math.abs(deltaY) / deltaT, // y speed
deltaY > 0 ? 1 : -1, // y direction
finalY // y now
this.inertia(targetWindow, dispatchTo, timestamp, // time now
Math.abs(deltaX) / deltaT, // speed
deltaX > 0 ? 1 : -1, // x direction
finalX, // x now
Math.abs(deltaY) / deltaT, // y speed
deltaY > 0 ? 1 : -1, // y direction
finalY // y now
);
}
@@ -282,7 +282,7 @@ export class Gesture extends Disposable {
}
}
private inertia(dispatchTo: readonly EventTarget[], t1: number, vX: number, dirX: number, x: number, vY: number, dirY: number, y: number): void {
private inertia(targetWindow: Window, dispatchTo: readonly EventTarget[], t1: number, vX: number, dirX: number, x: number, vY: number, dirY: number, y: number): void {
this.handle = DomUtils.scheduleAtNextAnimationFrame(() => {
const now = Date.now();
@@ -311,9 +311,9 @@ export class Gesture extends Disposable {
dispatchTo.forEach(d => d.dispatchEvent(evt));
if (!stopped) {
this.inertia(dispatchTo, now, vX, dirX, x + delta_pos_x, vY, dirY, y + delta_pos_y);
this.inertia(targetWindow, dispatchTo, now, vX, dirX, x + delta_pos_x, vY, dirY, y + delta_pos_y);
}
});
}, targetWindow);
}
private onTouchMove(e: TouchEvent): void {
@@ -128,7 +128,7 @@ export class BreadcrumbsWidget {
this._domNode.style.width = `${dim.width}px`;
this._domNode.style.height = `${dim.height}px`;
disposables.add(this._updateScrollbar());
}));
}, dom.getWindow(this._domNode)));
return disposables;
}
@@ -138,8 +138,8 @@ export class BreadcrumbsWidget {
this._scrollable.setRevealOnScroll(false);
this._scrollable.scanDomNode();
this._scrollable.setRevealOnScroll(true);
});
});
}, dom.getWindow(this._domNode));
}, dom.getWindow(this._domNode));
}
private _style(styleElement: HTMLStyleElement, style: IBreadcrumbsWidgetStyles): void {
+12 -6
View File
@@ -617,16 +617,22 @@ export class HistoryInputBox extends InputBox implements IHistoryNavigationWidge
readonly onDidBlur = this._onDidBlur.event;
constructor(container: HTMLElement, contextViewProvider: IContextViewProvider | undefined, options: IHistoryInputOptions) {
const NLS_PLACEHOLDER_HISTORY_HINT = nls.localize({ key: 'history.inputbox.hint', comment: ['Text will be prefixed with \u21C5 plus a single space, then used as a hint where input field keeps history'] }, "for history");
const NLS_PLACEHOLDER_HISTORY_HINT_SUFFIX = ` or \u21C5 ${NLS_PLACEHOLDER_HISTORY_HINT}`;
const NLS_PLACEHOLDER_HISTORY_HINT_SUFFIX_IN_PARENS = ` (\u21C5 ${NLS_PLACEHOLDER_HISTORY_HINT})`;
const NLS_PLACEHOLDER_HISTORY_HINT_SUFFIX_NO_PARENS = nls.localize({
key: 'history.inputbox.hint.suffix.noparens',
comment: ['Text is the suffix of an input field placeholder coming after the action the input field performs, this will be used when the input field ends in a closing parenthesis ")", for example "Filter (e.g. text, !exclude)". The character inserted into the final string is \u21C5 to represent the up and down arrow keys.']
}, ' or {0} for history', `\u21C5`);
const NLS_PLACEHOLDER_HISTORY_HINT_SUFFIX_IN_PARENS = nls.localize({
key: 'history.inputbox.hint.suffix.inparens',
comment: ['Text is the suffix of an input field placeholder coming after the action the input field performs, this will be used when the input field does NOT end in a closing parenthesis (eg. "Find"). The character inserted into the final string is \u21C5 to represent the up and down arrow keys.']
}, ' ({0} for history)', `\u21C5`);
super(container, contextViewProvider, options);
this.history = new HistoryNavigator<string>(options.history, 100);
// Function to append the history suffix to the placeholder if necessary
const addSuffix = () => {
if (options.showHistoryHint && options.showHistoryHint() && !this.placeholder.endsWith(NLS_PLACEHOLDER_HISTORY_HINT_SUFFIX) && !this.placeholder.endsWith(NLS_PLACEHOLDER_HISTORY_HINT_SUFFIX_IN_PARENS) && this.history.getHistory().length) {
const suffix = this.placeholder.endsWith(')') ? NLS_PLACEHOLDER_HISTORY_HINT_SUFFIX : NLS_PLACEHOLDER_HISTORY_HINT_SUFFIX_IN_PARENS;
if (options.showHistoryHint && options.showHistoryHint() && !this.placeholder.endsWith(NLS_PLACEHOLDER_HISTORY_HINT_SUFFIX_NO_PARENS) && !this.placeholder.endsWith(NLS_PLACEHOLDER_HISTORY_HINT_SUFFIX_IN_PARENS) && this.history.getHistory().length) {
const suffix = this.placeholder.endsWith(')') ? NLS_PLACEHOLDER_HISTORY_HINT_SUFFIX_NO_PARENS : NLS_PLACEHOLDER_HISTORY_HINT_SUFFIX_IN_PARENS;
const suffixedPlaceholder = this.placeholder + suffix;
if (options.showPlaceholderOnFocus && !dom.isActiveElement(this.input)) {
this.placeholder = suffixedPlaceholder;
@@ -666,7 +672,7 @@ export class HistoryInputBox extends InputBox implements IHistoryNavigationWidge
}
};
if (!resetPlaceholder(NLS_PLACEHOLDER_HISTORY_HINT_SUFFIX_IN_PARENS)) {
resetPlaceholder(NLS_PLACEHOLDER_HISTORY_HINT_SUFFIX);
resetPlaceholder(NLS_PLACEHOLDER_HISTORY_HINT_SUFFIX_NO_PARENS);
}
});
}
+4 -4
View File
@@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import { DataTransfers, IDragAndDropData } from 'vs/base/browser/dnd';
import { $, addDisposableListener, animate, Dimension, getContentHeight, getContentWidth, getTopLeftOffset, scheduleAtNextAnimationFrame } from 'vs/base/browser/dom';
import { $, addDisposableListener, animate, Dimension, getContentHeight, getContentWidth, getTopLeftOffset, getWindow, scheduleAtNextAnimationFrame } from 'vs/base/browser/dom';
import { DomEmitter } from 'vs/base/browser/event';
import { IMouseWheelEvent } from 'vs/base/browser/mouseEvent';
import { EventType as TouchEventType, Gesture, GestureEvent } from 'vs/base/browser/touch';
@@ -407,7 +407,7 @@ export class ListView<T> implements IListView<T> {
this.scrollable = this.disposables.add(new Scrollable({
forceIntegerValues: true,
smoothScrollDuration: (options.smoothScrolling ?? false) ? 125 : 0,
scheduleAtNextAnimationFrame: cb => scheduleAtNextAnimationFrame(cb)
scheduleAtNextAnimationFrame: cb => scheduleAtNextAnimationFrame(cb, getWindow(this.domNode))
}));
this.scrollableElement = this.disposables.add(new SmoothScrollableElement(this.rowsContainer, {
alwaysConsumeMouseWheel: options.alwaysConsumeMouseWheel ?? DefaultOptions.alwaysConsumeMouseWheel,
@@ -684,7 +684,7 @@ export class ListView<T> implements IListView<T> {
this.scrollableElement.setScrollDimensions({ scrollHeight: this.scrollHeight });
this.updateScrollWidth();
this.scrollableElementUpdateDisposable = null;
});
}, getWindow(this.domNode));
}
}
@@ -1291,7 +1291,7 @@ export class ListView<T> implements IListView<T> {
private setupDragAndDropScrollTopAnimation(event: DragEvent): void {
if (!this.dragOverAnimationDisposable) {
const viewTop = getTopLeftOffset(this.domNode).top;
this.dragOverAnimationDisposable = animate(this.animateDragAndDropScrollTop.bind(this, viewTop));
this.dragOverAnimationDisposable = animate(this.animateDragAndDropScrollTop.bind(this, viewTop), getWindow(this.domNode));
}
this.dragOverAnimationStopDisposable.dispose();
+1 -1
View File
@@ -630,7 +630,7 @@ export class MenuBar extends Disposable {
this.overflowLayoutScheduled = DOM.scheduleAtNextAnimationFrame(() => {
this.updateOverflowAction();
this.overflowLayoutScheduled = undefined;
});
}, DOM.getWindow(this.container));
}
this.setUnfocusedState();
@@ -576,7 +576,7 @@ export class ScrollableElement extends AbstractScrollableElement {
const scrollable = new Scrollable({
forceIntegerValues: true,
smoothScrollDuration: 0,
scheduleAtNextAnimationFrame: (callback) => dom.scheduleAtNextAnimationFrame(callback)
scheduleAtNextAnimationFrame: (callback) => dom.scheduleAtNextAnimationFrame(callback, dom.getWindow(element))
});
super(element, options, scrollable);
this._register(scrollable);
@@ -621,7 +621,7 @@ export class DomScrollableElement extends AbstractScrollableElement {
const scrollable = new Scrollable({
forceIntegerValues: false, // See https://github.com/microsoft/vscode/issues/139877
smoothScrollDuration: 0,
scheduleAtNextAnimationFrame: (callback) => dom.scheduleAtNextAnimationFrame(callback)
scheduleAtNextAnimationFrame: (callback) => dom.scheduleAtNextAnimationFrame(callback, dom.getWindow(element))
});
super(element, options, scrollable);
this._register(scrollable);
@@ -3,7 +3,7 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { $, addDisposableListener, append, scheduleAtNextAnimationFrame } from 'vs/base/browser/dom';
import { $, addDisposableListener, append, getWindow, scheduleAtNextAnimationFrame } from 'vs/base/browser/dom';
import { DomEmitter } from 'vs/base/browser/event';
import { ISashEvent as IBaseSashEvent, Orientation, Sash, SashState } from 'vs/base/browser/ui/sash/sash';
import { SmoothScrollableElement } from 'vs/base/browser/ui/scrollbar/scrollableElement';
@@ -584,7 +584,7 @@ export class SplitView<TLayoutContext = undefined, TView extends IView<TLayoutCo
this.scrollable = this._register(new Scrollable({
forceIntegerValues: true,
smoothScrollDuration: 125,
scheduleAtNextAnimationFrame
scheduleAtNextAnimationFrame: callback => scheduleAtNextAnimationFrame(callback, getWindow(this.el)),
}));
this.scrollableElement = this._register(new SmoothScrollableElement(this.viewContainer, {
vertical: this.orientation === Orientation.VERTICAL ? (options.scrollbarVisibility ?? ScrollbarVisibility.Auto) : ScrollbarVisibility.Hidden,
@@ -6,6 +6,7 @@
import { Disposable } from 'vs/base/common/lifecycle';
import { IDimension } from 'vs/editor/common/core/dimension';
import { Emitter, Event } from 'vs/base/common/event';
import { getWindow, scheduleAtNextAnimationFrame } from 'vs/base/browser/dom';
export class ElementSizeObserver extends Disposable {
@@ -65,10 +66,10 @@ export class ElementSizeObserver extends Disposable {
alreadyObservedThisAnimationFrame = true;
observeNow();
} finally {
requestAnimationFrame(() => {
scheduleAtNextAnimationFrame(() => {
alreadyObservedThisAnimationFrame = false;
update();
});
}, getWindow(this._referenceDomElement));
}
}
};
@@ -682,7 +682,7 @@ class TopBottomDragScrollingOperation extends Disposable {
this._position = position;
this._mouseEvent = mouseEvent;
this._lastTime = Date.now();
this._animationFrameDisposable = dom.scheduleAtNextAnimationFrame(() => this._execute());
this._animationFrameDisposable = dom.scheduleAtNextAnimationFrame(() => this._execute(), dom.getWindow(mouseEvent.browserEvent));
}
public override dispose(): void {
@@ -752,7 +752,7 @@ class TopBottomDragScrollingOperation extends Disposable {
}
this._dispatchMouse(mouseTarget, true, NavigationCommandRevealType.None);
this._animationFrameDisposable = dom.scheduleAtNextAnimationFrame(() => this._execute());
this._animationFrameDisposable = dom.scheduleAtNextAnimationFrame(() => this._execute(), dom.getWindow(mouseTarget.element));
}
}
+1 -1
View File
@@ -432,7 +432,7 @@ export class View extends ViewEventHandler {
private _scheduleRender(): void {
if (this._renderAnimationFrame === null) {
this._renderAnimationFrame = dom.runAtThisOrScheduleAtNextAnimationFrame(this._onRenderScheduled.bind(this), 100);
this._renderAnimationFrame = dom.runAtThisOrScheduleAtNextAnimationFrame(this._onRenderScheduled.bind(this), dom.getWindow(this.domNode.domNode), 100);
}
}
@@ -146,7 +146,7 @@ export class ViewCursor {
return null;
}
const window = dom.getWindow(this._domNode);
const window = dom.getWindow(this._domNode.domNode);
let width: number;
if (this._cursorStyle === TextEditorCursorStyle.Line) {
width = dom.computeScreenAwareSize(window, this._lineCursorWidth > 0 ? this._lineCursorWidth : 2);
@@ -1648,7 +1648,7 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE
model,
DOMLineBreaksComputerFactory.create(),
MonospaceLineBreaksComputerFactory.create(this._configuration.options),
(callback) => dom.scheduleAtNextAnimationFrame(callback),
(callback) => dom.scheduleAtNextAnimationFrame(callback, dom.getWindow(this._domElement)),
this.languageConfigurationService,
this._themeService,
attachedView,
@@ -2,7 +2,7 @@
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { $, h } from 'vs/base/browser/dom';
import { $, getWindow, h } from 'vs/base/browser/dom';
import { IBoundarySashes } from 'vs/base/browser/ui/sash/sash';
import { findLast } from 'vs/base/common/arraysFind';
import { onUnexpectedError } from 'vs/base/common/errors';
@@ -178,6 +178,7 @@ export class DiffEditorWidget extends DelegatingEditor implements IDiffEditor {
/** @description ViewZoneManager */
store.add(this._instantiationService.createInstance(
readHotReloadableExport(ViewZoneManager, reader),
getWindow(this._domElement),
this._editors,
this._diffModel,
this._options,
@@ -42,14 +42,15 @@ export class ViewZoneManager extends Disposable {
private readonly _originalTopPadding = observableValue(this, 0);
private readonly _originalScrollTop: IObservable<number>;
private readonly _originalScrollOffset = observableValue<number, boolean>(this, 0);
private readonly _originalScrollOffsetAnimated = animatedObservable(this._originalScrollOffset, this._store);
private readonly _originalScrollOffsetAnimated = animatedObservable(this._targetWindow, this._originalScrollOffset, this._store);
private readonly _modifiedTopPadding = observableValue(this, 0);
private readonly _modifiedScrollTop: IObservable<number>;
private readonly _modifiedScrollOffset = observableValue<number, boolean>(this, 0);
private readonly _modifiedScrollOffsetAnimated = animatedObservable(this._modifiedScrollOffset, this._store);
private readonly _modifiedScrollOffsetAnimated = animatedObservable(this._targetWindow, this._modifiedScrollOffset, this._store);
constructor(
private readonly _targetWindow: Window,
private readonly _editors: DiffEditorEditors,
private readonly _diffModel: IObservable<DiffEditorViewModel | undefined>,
private readonly _options: DiffEditorOptions,
@@ -123,7 +123,7 @@ export class ObservableElementSizeObserver extends Disposable {
}
}
export function animatedObservable(base: IObservable<number, boolean>, store: DisposableStore): IObservable<number> {
export function animatedObservable(targetWindow: Window, base: IObservable<number, boolean>, store: DisposableStore): IObservable<number> {
let targetVal = base.get();
let startVal = targetVal;
let curVal = targetVal;
@@ -160,7 +160,7 @@ export function animatedObservable(base: IObservable<number, boolean>, store: Di
curVal = Math.floor(easeOutExpo(passedMs, startVal, targetVal - startVal, durationMs));
if (passedMs < durationMs) {
animationFrame = requestAnimationFrame(update);
animationFrame = targetWindow.requestAnimationFrame(update);
} else {
curVal = targetVal;
}
@@ -571,7 +571,7 @@ export class SuggestWidget implements IDisposable {
this._layout(this.element.size);
// Reset focus border
this._details.widget.domNode.classList.remove('focused');
});
}, dom.getWindow(this.element.domNode));
}
focusSelected(): void {
@@ -721,7 +721,7 @@ export class SuggestWidget implements IDisposable {
this._positionDetails();
this.editor.focus();
this.element.domNode.classList.add('shows-details');
});
}, dom.getWindow(this.element.domNode));
}
toggleExplainMode(): void {
@@ -41,6 +41,7 @@ class EditorScopedQuickInputService extends QuickInputService {
_serviceBrand: undefined,
get hasContainer() { return true; },
get container() { return widget.getDomNode(); },
getContainer() { return widget.getDomNode(); },
get containers() { return [widget.getDomNode()]; },
get activeContainer() { return widget.getDomNode(); },
get mainContainerDimension() { return editor.getLayoutInfo(); },
@@ -54,6 +54,10 @@ class StandaloneLayoutService implements ILayoutService {
return activeCodeEditor?.getContainerDomNode() ?? this.container;
}
getContainer() {
return this.activeContainer;
}
focus(): void {
this._codeEditorService.getFocusedCodeEditor()?.focus();
}
@@ -79,7 +79,7 @@ export class MockScopableContextKeyService extends MockContextKeyService {
* Don't implement this for all tests since we rarely depend on this behavior and it isn't implemented fully
*/
public override createScoped(domNote: HTMLElement): IScopedContextKeyService {
return new MockContextKeyService();
return new MockScopableContextKeyService();
}
}
@@ -81,6 +81,11 @@ export interface ILayoutService {
*/
readonly containers: Iterable<HTMLElement>;
/**
* Get the container for the given window.
*/
getContainer(window: Window): HTMLElement;
/**
* An offset to use for positioning elements inside the main container.
*/
@@ -128,7 +128,7 @@ export class Menubar {
this.fallbackMenuHandlers['workbench.action.openWorkspace'] = (menuItem, win, event) => this.nativeHostMainService.pickWorkspaceAndOpen(undefined, { forceNewWindow: this.isOptionClick(event), telemetryExtraData: { from: telemetryFrom } });
// Recent Menu Items
this.fallbackMenuHandlers['workbench.action.clearRecentFiles'] = () => this.workspacesHistoryMainService.clearRecentlyOpened();
this.fallbackMenuHandlers['workbench.action.clearRecentFiles'] = () => this.workspacesHistoryMainService.clearRecentlyOpened({ confirm: true /* ask for confirmation */ });
// Help Menu Items
const youTubeUrl = this.productService.youTubeUrl;
@@ -377,10 +377,10 @@ export class CommandDetectionCapability extends Disposable implements ICommandDe
// Conpty could have the wrong cursor position at this point.
if (!this._cursorOnNextLine() || !prompt) {
this._windowsPromptPollingInProcess = true;
// Poll for 200ms until the cursor position is correct.
// Poll for 1000ms until the cursor position is correct.
let i = 0;
for (; i < 20; i++) {
await timeout(10);
for (; i < 50; i++) {
await timeout(20);
prompt = this._getWindowsPrompt();
if (this._store.isDisposed || !this._windowsPromptPollingInProcess || this._cursorOnNextLine() && prompt) {
if (!this._windowsPromptPollingInProcess) {
@@ -390,7 +390,7 @@ export class CommandDetectionCapability extends Disposable implements ICommandDe
}
}
this._windowsPromptPollingInProcess = false;
if (i === 20) {
if (i >= 50) {
this._logService.debug('CommandDetectionCapability#_handleCommandStartWindows reached max attempts, ', this._cursorOnNextLine(), this._getWindowsPrompt());
} else if (prompt) {
// use the regex to set the position as it's possible input has occurred
@@ -428,9 +428,11 @@ export class CommandDetectionCapability extends Disposable implements ICommandDe
private _cursorOnNextLine(): boolean {
const lastCommand = this.commands.at(-1);
// There is only a single command, so this check is unnecessary
if (!lastCommand) {
return false;
return true;
}
const cursorYAbsolute = this._terminal.buffer.active.baseY + this._terminal.buffer.active.cursorY;
// If the cursor position is within the last command, we should poll.
const lastCommandYAbsolute = (lastCommand.endMarker ? lastCommand.endMarker.line : lastCommand.marker?.line) ?? -1;
@@ -442,8 +444,26 @@ export class CommandDetectionCapability extends Disposable implements ICommandDe
if (!line) {
return;
}
// TODO: fine tune prompt regex to accomodate for unique configurtions.
return line.translateToString(true)?.match(/^(?<prompt>(\(.+\)\s)?(?:PS.+>\s)|(?:[A-Z]:\\.*>))/)?.groups?.prompt;
// TODO: fine tune prompt regex to accomodate for unique configurations.
const lineText = line.translateToString(true);
if (!lineText) {
return;
}
// PowerShell
const pwshMatch = lineText.match(/(?<prompt>(\(.+\)\s)?(?:PS.+>\s?))/);
if (pwshMatch) {
let prompt = pwshMatch?.groups?.prompt;
if (lineText === prompt && prompt.endsWith('>')) {
// Conpty may not 'render' the space at the end of the prompt
prompt += ' ';
}
return prompt;
}
// Command Prompt
const cmdMatch = lineText.match(/^(?<prompt>(\(.+\)\s)?(?:[A-Z]:\\.*>))/);
return cmdMatch?.groups?.prompt;
}
handleGenericCommand(options?: IHandleCommandOptions): void {
@@ -4,7 +4,6 @@
*--------------------------------------------------------------------------------------------*/
import { fail, strictEqual } from 'assert';
import { DisposableStore } from 'vs/base/common/lifecycle';
import { ensureNoDisposablesAreLeakedInTestSuite } from 'vs/base/test/common/utils';
import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock';
import { ConsoleLogger, ILogService } from 'vs/platform/log/common/log';
@@ -12,37 +11,30 @@ import { LogService } from 'vs/platform/log/common/logService';
import { RequestStore } from 'vs/platform/terminal/common/requestStore';
suite('RequestStore', () => {
let disposables: DisposableStore;
let instantiationService: TestInstantiationService;
setup(() => {
disposables = new DisposableStore();
instantiationService = new TestInstantiationService();
instantiationService.stub(ILogService, new LogService(new ConsoleLogger()));
});
teardown(() => {
instantiationService.dispose();
disposables.dispose();
});
ensureNoDisposablesAreLeakedInTestSuite();
const store = ensureNoDisposablesAreLeakedInTestSuite();
test('should resolve requests', async () => {
const store: RequestStore<{ data: string }, { arg: string }> = disposables.add(instantiationService.createInstance(RequestStore<{ data: string }, { arg: string }>, undefined));
const requestStore: RequestStore<{ data: string }, { arg: string }> = store.add(instantiationService.createInstance(RequestStore<{ data: string }, { arg: string }>, undefined));
let eventArgs: { requestId: number; arg: string } | undefined;
disposables.add(store.onCreateRequest(e => eventArgs = e));
const request = store.createRequest({ arg: 'foo' });
store.add(requestStore.onCreateRequest(e => eventArgs = e));
const request = requestStore.createRequest({ arg: 'foo' });
strictEqual(typeof eventArgs?.requestId, 'number');
strictEqual(eventArgs?.arg, 'foo');
store.acceptReply(eventArgs!.requestId, { data: 'bar' });
requestStore.acceptReply(eventArgs!.requestId, { data: 'bar' });
const result = await request;
strictEqual(result.data, 'bar');
});
test('should reject the promise when the request times out', async () => {
const store: RequestStore<{ data: string }, { arg: string }> = disposables.add(instantiationService.createInstance(RequestStore<{ data: string }, { arg: string }>, 1));
const request = store.createRequest({ arg: 'foo' });
const requestStore: RequestStore<{ data: string }, { arg: string }> = store.add(instantiationService.createInstance(RequestStore<{ data: string }, { arg: string }>, 1));
const request = requestStore.createRequest({ arg: 'foo' });
let threw = false;
try {
await request;
@@ -13,7 +13,7 @@ import { zoomLevelToZoomFactor } from 'vs/platform/window/common/window';
* browser helper so that it can be accessed in non-electron layers.
*/
export function applyZoom(zoomLevel: number): void {
for (const window of getWindows()) {
for (const { window } of getWindows()) {
getGlobals(window)?.webFrame?.setZoomLevel(zoomLevel);
}
setZoomFactor(zoomLevelToZoomFactor(zoomLevel));
@@ -24,6 +24,7 @@ import { IRecent, IRecentFile, IRecentFolder, IRecentlyOpened, IRecentWorkspace,
import { IWorkspaceIdentifier, WORKSPACE_EXTENSION } from 'vs/platform/workspace/common/workspace';
import { IWorkspacesManagementMainService } from 'vs/platform/workspaces/electron-main/workspacesManagementMainService';
import { ResourceMap } from 'vs/base/common/map';
import { IDialogMainService } from 'vs/platform/dialogs/electron-main/dialogMainService';
export const IWorkspacesHistoryMainService = createDecorator<IWorkspacesHistoryMainService>('workspacesHistoryMainService');
@@ -36,7 +37,7 @@ export interface IWorkspacesHistoryMainService {
addRecentlyOpened(recents: IRecent[]): Promise<void>;
getRecentlyOpened(): Promise<IRecentlyOpened>;
removeRecentlyOpened(paths: URI[]): Promise<void>;
clearRecentlyOpened(): Promise<void>;
clearRecentlyOpened(options?: { confirm?: boolean }): Promise<void>;
}
export class WorkspacesHistoryMainService extends Disposable implements IWorkspacesHistoryMainService {
@@ -54,7 +55,8 @@ export class WorkspacesHistoryMainService extends Disposable implements IWorkspa
@ILogService private readonly logService: ILogService,
@IWorkspacesManagementMainService private readonly workspacesManagementMainService: IWorkspacesManagementMainService,
@ILifecycleMainService private readonly lifecycleMainService: ILifecycleMainService,
@IApplicationStorageMainService private readonly applicationStorageMainService: IApplicationStorageMainService
@IApplicationStorageMainService private readonly applicationStorageMainService: IApplicationStorageMainService,
@IDialogMainService private readonly dialogMainService: IDialogMainService
) {
super();
@@ -157,7 +159,24 @@ export class WorkspacesHistoryMainService extends Disposable implements IWorkspa
}
}
async clearRecentlyOpened(): Promise<void> {
async clearRecentlyOpened(options?: { confirm?: boolean }): Promise<void> {
if (options?.confirm) {
const { response } = await this.dialogMainService.showMessageBox({
type: 'warning',
buttons: [
localize({ key: 'clearButtonLabel', comment: ['&& denotes a mnemonic'] }, "&&Clear"),
localize({ key: 'cancel', comment: ['&& denotes a mnemonic'] }, "&&Cancel")
],
message: localize('confirmClearRecentsMessage', "Do you want to clear all recently opened files and workspaces?"),
detail: localize('confirmClearDetail', "This action is irreversible!"),
cancelId: 1
});
if (response !== 0) {
return;
}
}
await this.saveRecentlyOpened({ workspaces: [], files: [] });
app.clearRecentDocuments();
@@ -9,9 +9,9 @@ import { localize } from 'vs/nls';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { DomEmitter } from 'vs/base/browser/event';
import { Color } from 'vs/base/common/color';
import { Event } from 'vs/base/common/event';
import { Emitter, Event } from 'vs/base/common/event';
import { IDisposable, toDisposable, dispose, DisposableStore, setDisposableTracker, DisposableTracker, DisposableInfo } from 'vs/base/common/lifecycle';
import { getDomNodePagePosition, createStyleSheet, createCSSRule, append, $, getActiveDocument } from 'vs/base/browser/dom';
import { getDomNodePagePosition, createStyleSheet, createCSSRule, append, $, getActiveDocument, onDidRegisterWindow, getWindows } from 'vs/base/browser/dom';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { ContextKeyExpr, IContextKeyService, RawContextKey } from 'vs/platform/contextkey/common/contextkey';
import { Context } from 'vs/platform/contextkey/browser/contextKeyService';
@@ -130,13 +130,34 @@ class ToggleScreencastModeAction extends Action2 {
const disposables = new DisposableStore();
const container = layoutService.container;
const container = layoutService.activeContainer;
const mouseMarker = append(container, $('.screencast-mouse'));
disposables.add(toDisposable(() => mouseMarker.remove()));
const onMouseDown = disposables.add(new DomEmitter(container, 'mousedown', true));
const onMouseUp = disposables.add(new DomEmitter(container, 'mouseup', true));
const onMouseMove = disposables.add(new DomEmitter(container, 'mousemove', true));
const keyboardMarker = append(container, $('.screencast-keyboard'));
disposables.add(toDisposable(() => keyboardMarker.remove()));
const onMouseDown = disposables.add(new Emitter<MouseEvent>());
const onMouseUp = disposables.add(new Emitter<MouseEvent>());
const onMouseMove = disposables.add(new Emitter<MouseEvent>());
function registerContainerListeners(container: HTMLElement, disposables: DisposableStore): void {
disposables.add(disposables.add(new DomEmitter(container, 'mousedown', true)).event(e => onMouseDown.fire(e)));
disposables.add(disposables.add(new DomEmitter(container, 'mouseup', true)).event(e => onMouseUp.fire(e)));
disposables.add(disposables.add(new DomEmitter(container, 'mousemove', true)).event(e => onMouseMove.fire(e)));
}
for (const { window, disposables } of getWindows()) {
registerContainerListeners(layoutService.getContainer(window), disposables);
}
disposables.add(onDidRegisterWindow(({ window, disposables }) => registerContainerListeners(layoutService.getContainer(window), disposables)));
disposables.add(layoutService.onDidChangeActiveContainer(() => {
layoutService.activeContainer.appendChild(mouseMarker);
layoutService.activeContainer.appendChild(keyboardMarker);
}));
const updateMouseIndicatorColor = () => {
mouseMarker.style.borderColor = Color.fromHex(configurationService.getValue<string>('screencastMode.mouseIndicatorColor')).toString();
@@ -172,9 +193,6 @@ class ToggleScreencastModeAction extends Action2 {
});
}));
const keyboardMarker = append(container, $('.screencast-keyboard'));
disposables.add(toDisposable(() => keyboardMarker.remove()));
const updateKeyboardFontSize = () => {
keyboardMarker.style.fontSize = `${clamp(configurationService.getValue<number>('screencastMode.fontSize') || 56, 20, 100)}px`;
};
@@ -214,10 +232,23 @@ class ToggleScreencastModeAction extends Action2 {
}
}));
const onKeyDown = disposables.add(new DomEmitter(window, 'keydown', true));
const onCompositionStart = disposables.add(new DomEmitter(window, 'compositionstart', true));
const onCompositionUpdate = disposables.add(new DomEmitter(window, 'compositionupdate', true));
const onCompositionEnd = disposables.add(new DomEmitter(window, 'compositionend', true));
const onKeyDown = disposables.add(new Emitter<KeyboardEvent>());
const onCompositionStart = disposables.add(new Emitter<CompositionEvent>());
const onCompositionUpdate = disposables.add(new Emitter<CompositionEvent>());
const onCompositionEnd = disposables.add(new Emitter<CompositionEvent>());
function registerWindowListeners(window: Window, disposables: DisposableStore): void {
disposables.add(disposables.add(new DomEmitter(window, 'keydown', true)).event(e => onKeyDown.fire(e)));
disposables.add(disposables.add(new DomEmitter(window, 'compositionstart', true)).event(e => onCompositionStart.fire(e)));
disposables.add(disposables.add(new DomEmitter(window, 'compositionupdate', true)).event(e => onCompositionUpdate.fire(e)));
disposables.add(disposables.add(new DomEmitter(window, 'compositionend', true)).event(e => onCompositionEnd.fire(e)));
}
for (const { window, disposables } of getWindows()) {
registerWindowListeners(window, disposables);
}
disposables.add(onDidRegisterWindow(({ window, disposables }) => registerWindowListeners(window, disposables)));
let length = 0;
let composing: Element | undefined = undefined;
+1 -5
View File
@@ -7,7 +7,7 @@ import { Event } from 'vs/base/common/event';
import { Disposable } from 'vs/base/common/lifecycle';
import { IContextKeyService, IContextKey, setConstant as setConstantContextKey } from 'vs/platform/contextkey/common/contextkey';
import { InputFocusedContext, IsMacContext, IsLinuxContext, IsWindowsContext, IsWebContext, IsMacNativeContext, IsDevelopmentContext, IsIOSContext, ProductQualityContext, IsMobileContext } from 'vs/platform/contextkey/common/contextkeys';
import { SplitEditorsVertically, InEditorZenModeContext, ActiveEditorCanRevertContext, ActiveEditorGroupLockedContext, ActiveEditorCanSplitInGroupContext, SideBySideEditorActiveContext, AuxiliaryBarVisibleContext, SideBarVisibleContext, PanelAlignmentContext, PanelMaximizedContext, PanelVisibleContext, ActiveEditorContext, EditorsVisibleContext, TextCompareEditorVisibleContext, TextCompareEditorActiveContext, ActiveEditorGroupEmptyContext, MultipleEditorGroupsContext, EmbedderIdentifierContext, EditorTabsVisibleContext, IsCenteredLayoutContext, ActiveEditorGroupIndexContext, ActiveEditorGroupLastContext, ActiveEditorReadonlyContext, EditorAreaVisibleContext, ActiveEditorAvailableEditorIdsContext, DirtyWorkingCopiesContext, EmptyWorkspaceSupportContext, EnterMultiRootWorkspaceSupportContext, HasWebFileSystemAccess, IsFullscreenContext, OpenFolderWorkspaceSupportContext, RemoteNameContext, VirtualWorkspaceContext, WorkbenchStateContext, WorkspaceFolderCountContext, PanelPositionContext, TemporaryWorkspaceContext, ActiveEditorCanToggleReadonlyContext, applyAvailableEditorIds, MaximizedEditorGroupContext, TitleBarVisibleContext, TitleBarStyleContext } from 'vs/workbench/common/contextkeys';
import { SplitEditorsVertically, InEditorZenModeContext, ActiveEditorCanRevertContext, ActiveEditorGroupLockedContext, ActiveEditorCanSplitInGroupContext, SideBySideEditorActiveContext, AuxiliaryBarVisibleContext, SideBarVisibleContext, PanelAlignmentContext, PanelMaximizedContext, PanelVisibleContext, ActiveEditorContext, EditorsVisibleContext, TextCompareEditorVisibleContext, TextCompareEditorActiveContext, ActiveEditorGroupEmptyContext, EmbedderIdentifierContext, EditorTabsVisibleContext, IsCenteredLayoutContext, ActiveEditorGroupIndexContext, ActiveEditorGroupLastContext, ActiveEditorReadonlyContext, EditorAreaVisibleContext, ActiveEditorAvailableEditorIdsContext, DirtyWorkingCopiesContext, EmptyWorkspaceSupportContext, EnterMultiRootWorkspaceSupportContext, HasWebFileSystemAccess, IsFullscreenContext, OpenFolderWorkspaceSupportContext, RemoteNameContext, VirtualWorkspaceContext, WorkbenchStateContext, WorkspaceFolderCountContext, PanelPositionContext, TemporaryWorkspaceContext, ActiveEditorCanToggleReadonlyContext, applyAvailableEditorIds, TitleBarVisibleContext, TitleBarStyleContext, MultipleEditorGroupsContext } from 'vs/workbench/common/contextkeys';
import { TEXT_DIFF_EDITOR_ID, EditorInputCapabilities, SIDE_BY_SIDE_EDITOR_ID, EditorResourceAccessor, SideBySideEditor } from 'vs/workbench/common/editor';
import { trackFocus, addDisposableListener, EventType, onDidRegisterWindow } from 'vs/base/browser/dom';
import { preferredSideBySideGroupDirection, GroupDirection, IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
@@ -45,7 +45,6 @@ export class WorkbenchContextKeysHandler extends Disposable {
private activeEditorGroupLast: IContextKey<boolean>;
private activeEditorGroupLocked: IContextKey<boolean>;
private multipleEditorGroupsContext: IContextKey<boolean>;
private maximizedEditorGroupContext: IContextKey<boolean>;
private editorsVisibleContext: IContextKey<boolean>;
@@ -139,7 +138,6 @@ export class WorkbenchContextKeysHandler extends Disposable {
this.activeEditorGroupLast = ActiveEditorGroupLastContext.bindTo(this.contextKeyService);
this.activeEditorGroupLocked = ActiveEditorGroupLockedContext.bindTo(this.contextKeyService);
this.multipleEditorGroupsContext = MultipleEditorGroupsContext.bindTo(this.contextKeyService);
this.maximizedEditorGroupContext = MaximizedEditorGroupContext.bindTo(this.contextKeyService);
// Working Copies
this.dirtyWorkingCopiesContext = DirtyWorkingCopiesContext.bindTo(this.contextKeyService);
@@ -238,8 +236,6 @@ export class WorkbenchContextKeysHandler extends Disposable {
this._register(this.editorGroupService.onDidChangeActiveGroup(() => this.updateEditorGroupContextKeys()));
this._register(this.editorGroupService.onDidChangeGroupLocked(() => this.updateEditorGroupContextKeys()));
this._register(this.editorGroupService.onDidChangeGroupMaximized((maximized) => this.maximizedEditorGroupContext.set(maximized)));
this._register(this.editorGroupService.onDidChangeEditorPartOptions(() => this.updateEditorAreaContextKeys()));
this._register(Event.runAndSubscribe(onDidRegisterWindow, ({ window, disposables }) => disposables.add(addDisposableListener(window, EventType.FOCUS_IN, () => this.updateInputContextKeys(window.document), true)), { window, disposables: this._store }));
+17 -10
View File
@@ -52,7 +52,7 @@ import { IAuxiliaryWindowService, isAuxiliaryWindow } from 'vs/workbench/service
//#region Layout Implementation
interface ILayoutRuntimeState {
activeContainer: 'main' | number /* window ID */;
activeContainerId: 'main' | number /* window ID */;
fullscreen: boolean;
maximized: boolean;
hasFocus: boolean;
@@ -170,7 +170,7 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi
get activeContainer() { return this.getContainerFromDocument(getActiveDocument()); }
get containers(): Iterable<HTMLElement> {
const containers: HTMLElement[] = [];
for (const window of getWindows()) {
for (const { window } of getWindows()) {
containers.push(this.getContainerFromDocument(window.document));
}
@@ -453,8 +453,8 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi
private onWindowFocusChanged(hasFocus: boolean): void {
if (hasFocus) {
const activeContainerId = this.getActiveContainerId();
if (this.state.runtime.activeContainer !== activeContainerId) {
this.state.runtime.activeContainer = activeContainerId;
if (this.state.runtime.activeContainerId !== activeContainerId) {
this.state.runtime.activeContainerId = activeContainerId;
this._onDidChangeActiveContainer.fire();
}
}
@@ -615,7 +615,7 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi
// Layout Runtime State
const layoutRuntimeState: ILayoutRuntimeState = {
activeContainer: this.getActiveContainerId(),
activeContainerId: this.getActiveContainerId(),
fullscreen: isFullscreen(),
hasFocus: this.hostService.hasFocus,
maximized: false,
@@ -1125,12 +1125,19 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi
}
}
getContainer(part: Parts): HTMLElement | undefined {
if (!this.parts.get(part)) {
return undefined;
getContainer(window: Window): HTMLElement;
getContainer(part: Parts): HTMLElement | undefined;
getContainer(windowOrPart: Window | Parts): HTMLElement | undefined {
if (typeof windowOrPart === 'string') {
const part = windowOrPart;
if (!this.parts.get(part)) {
return undefined;
}
return this.getPart(part).getContainer();
}
return this.getPart(part).getContainer();
return this.getContainerFromDocument(windowOrPart.document);
}
isVisible(part: Parts): boolean {
@@ -1185,7 +1192,7 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi
}
// with the command center enabled, we should always show
if (this.configurationService.getValue<boolean>('window.commandCenter')) {
if (this.configurationService.getValue<boolean>(LayoutSettings.COMMAND_CENTER)) {
return true;
}
@@ -9,8 +9,8 @@ import { IEditorPaneRegistry, EditorPaneDescriptor } from 'vs/workbench/browser/
import { IEditorFactoryRegistry, EditorExtensions } from 'vs/workbench/common/editor';
import {
TextCompareEditorActiveContext, ActiveEditorPinnedContext, EditorGroupEditorsCountContext, ActiveEditorStickyContext, ActiveEditorAvailableEditorIdsContext,
MultipleEditorGroupsContext, ActiveEditorDirtyContext, ActiveEditorGroupLockedContext, ActiveEditorCanSplitInGroupContext, SideBySideEditorActiveContext,
EditorTabsVisibleContext, ActiveEditorLastInGroupContext, MaximizedEditorGroupContext
EditorPartMultipleEditorGroupsContext, ActiveEditorDirtyContext, ActiveEditorGroupLockedContext, ActiveEditorCanSplitInGroupContext, SideBySideEditorActiveContext,
EditorTabsVisibleContext, ActiveEditorLastInGroupContext, EditorPartMaximizedEditorGroupContext, MultipleEditorGroupsContext
} from 'vs/workbench/common/contextkeys';
import { SideBySideEditorInput, SideBySideEditorInputSerializer } from 'vs/workbench/common/editor/sideBySideEditorInput';
import { TextResourceEditor } from 'vs/workbench/browser/parts/editor/textResourceEditor';
@@ -384,8 +384,8 @@ MenuRegistry.appendMenuItem(MenuId.EditorTitle, { command: { id: SHOW_EDITORS_IN
MenuRegistry.appendMenuItem(MenuId.EditorTitle, { command: { id: CLOSE_EDITORS_IN_GROUP_COMMAND_ID, title: localize('closeAll', "Close All") }, group: '5_close', order: 10 });
MenuRegistry.appendMenuItem(MenuId.EditorTitle, { command: { id: CLOSE_SAVED_EDITORS_COMMAND_ID, title: localize('closeAllSaved', "Close Saved") }, group: '5_close', order: 20 });
MenuRegistry.appendMenuItem(MenuId.EditorTitle, { command: { id: TOGGLE_KEEP_EDITORS_COMMAND_ID, title: localize('togglePreviewMode', "Enable Preview Editors"), toggled: ContextKeyExpr.has('config.workbench.editor.enablePreview') }, group: '7_settings', order: 10 });
MenuRegistry.appendMenuItem(MenuId.EditorTitle, { command: { id: TOGGLE_MAXIMIZE_EDITOR_GROUP, title: localize('maximizeGroup', "Maximize Group") }, group: '8_group_operations', order: 5, when: ContextKeyExpr.and(MaximizedEditorGroupContext.negate(), MultipleEditorGroupsContext) });
MenuRegistry.appendMenuItem(MenuId.EditorTitle, { command: { id: TOGGLE_MAXIMIZE_EDITOR_GROUP, title: localize('unmaximizeGroup', "Unmaximize Group") }, group: '8_group_operations', order: 5, when: MaximizedEditorGroupContext });
MenuRegistry.appendMenuItem(MenuId.EditorTitle, { command: { id: TOGGLE_MAXIMIZE_EDITOR_GROUP, title: localize('maximizeGroup', "Maximize Group") }, group: '8_group_operations', order: 5, when: ContextKeyExpr.and(EditorPartMaximizedEditorGroupContext.negate(), EditorPartMultipleEditorGroupsContext) });
MenuRegistry.appendMenuItem(MenuId.EditorTitle, { command: { id: TOGGLE_MAXIMIZE_EDITOR_GROUP, title: localize('unmaximizeGroup', "Unmaximize Group") }, group: '8_group_operations', order: 5, when: EditorPartMaximizedEditorGroupContext });
MenuRegistry.appendMenuItem(MenuId.EditorTitle, { command: { id: TOGGLE_LOCK_GROUP_COMMAND_ID, title: localize('lockGroup', "Lock Group"), toggled: ActiveEditorGroupLockedContext }, group: '8_group_operations', order: 10, when: MultipleEditorGroupsContext });
function appendEditorToolItem(primary: ICommandAction, when: ContextKeyExpression | undefined, order: number, alternative?: ICommandAction, precondition?: ContextKeyExpression | undefined): void {
@@ -601,7 +601,7 @@ MenuRegistry.appendMenuItem(MenuId.MenubarRecentMenu, {
group: 'z_clear',
command: {
id: ClearRecentFilesAction.ID,
title: localize({ key: 'miClearRecentOpen', comment: ['&& denotes a mnemonic'] }, "&&Clear Recently Opened")
title: localize({ key: 'miClearRecentOpen', comment: ['&& denotes a mnemonic'] }, "&&Clear Recently Opened...")
},
order: 1
});
@@ -28,7 +28,9 @@ export const DEFAULT_EDITOR_MAX_DIMENSIONS = new Dimension(Number.POSITIVE_INFIN
export const DEFAULT_EDITOR_PART_OPTIONS: IEditorPartOptions = {
showTabs: 'multiple',
highlightModifiedTabs: false,
tabCloseButton: 'right',
tabActionLocation: 'right',
tabActionCloseVisibility: true,
tabActionUnpinVisibility: true,
tabSizing: 'fit',
tabSizingFixedMinWidth: 50,
tabSizingFixedMaxWidth: 160,
@@ -104,6 +106,8 @@ function validateEditorPartOptions(options: IEditorPartOptions): void {
'wrapTabs',
'scrollToSwitchTabs',
'highlightModifiedTabs',
'tabActionCloseVisibility',
'tabActionUnpinVisibility',
'pinnedTabsOnSeparateRow',
'focusRecentEditorAfterClose',
'showIcons',
@@ -138,7 +142,7 @@ function validateEditorPartOptions(options: IEditorPartOptions): void {
// String options
const stringOptions: Array<[OptionalStringKey<IEditorPartOptions>, Array<string>]> = [
['showTabs', ['multiple', 'single', 'none']],
['tabCloseButton', ['left', 'right', 'off']],
['tabActionLocation', ['left', 'right']],
['tabSizing', ['fit', 'shrink', 'fixed']],
['pinnedTabSizing', ['normal', 'compact', 'shrink']],
['tabHeight', ['default', 'compact']],
@@ -33,7 +33,7 @@ import { KeyChord, KeyCode, KeyMod } from 'vs/base/common/keyCodes';
import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
import { ILogService } from 'vs/platform/log/common/log';
import { Categories } from 'vs/platform/action/common/actionCommonCategories';
import { ActiveEditorAvailableEditorIdsContext, ActiveEditorContext, ActiveEditorGroupEmptyContext, MaximizedEditorGroupContext, MultipleEditorGroupsContext } from 'vs/workbench/common/contextkeys';
import { ActiveEditorAvailableEditorIdsContext, ActiveEditorContext, ActiveEditorGroupEmptyContext, EditorPartMaximizedEditorGroupContext, EditorPartMultipleEditorGroupsContext } from 'vs/workbench/common/contextkeys';
import { URI } from 'vs/base/common/uri';
import { getActiveDocument } from 'vs/base/browser/dom';
@@ -1073,7 +1073,7 @@ export class MaximizeGroupHideSidebarAction extends Action2 {
title: { value: localize('maximizeEditorHideSidebar', "Maximize Editor Group and Hide Side Bars"), original: 'Maximize Editor Group and Hide Side Bars' },
f1: true,
category: Categories.View,
precondition: ContextKeyExpr.and(MaximizedEditorGroupContext.negate(), MultipleEditorGroupsContext)
precondition: ContextKeyExpr.and(EditorPartMaximizedEditorGroupContext.negate(), EditorPartMultipleEditorGroupsContext)
});
}
@@ -1098,7 +1098,7 @@ export class ToggleMaximizeEditorGroupAction extends Action2 {
title: { value: localize('toggleMaximizeEditorGroup', "Toggle Maximize Editor Group"), original: 'Toggle Maximize Editor Group' },
f1: true,
category: Categories.View,
precondition: ContextKeyExpr.or(MultipleEditorGroupsContext, MaximizedEditorGroupContext),
precondition: ContextKeyExpr.or(EditorPartMultipleEditorGroupsContext, EditorPartMaximizedEditorGroupContext),
keybinding: {
weight: KeybindingWeight.WorkbenchContrib,
primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KeyK, KeyMod.CtrlCmd | KeyCode.KeyM),
@@ -1107,16 +1107,16 @@ export class ToggleMaximizeEditorGroupAction extends Action2 {
id: MenuId.EditorTitle,
order: -10000, // towards the front
group: 'navigation',
when: MaximizedEditorGroupContext
when: EditorPartMaximizedEditorGroupContext
},
{
id: MenuId.EmptyEditorGroup,
order: -10000, // towards the front
group: 'navigation',
when: MaximizedEditorGroupContext
when: EditorPartMaximizedEditorGroupContext
}],
icon: Codicon.screenFull,
toggled: MaximizedEditorGroupContext,
toggled: EditorPartMaximizedEditorGroupContext,
});
}
@@ -1600,7 +1600,7 @@ export class ClearRecentFilesAction extends Action2 {
constructor() {
super({
id: ClearRecentFilesAction.ID,
title: { value: localize('clearRecentFiles', "Clear Recently Opened"), original: 'Clear Recently Opened' },
title: { value: localize('clearRecentFiles', "Clear Recently Opened..."), original: 'Clear Recently Opened...' },
f1: true,
category: Categories.File
});
@@ -28,8 +28,7 @@ const openFileNonMacOnly: WatermarkEntry = { text: localize('watermark.openFile'
const openFolderNonMacOnly: WatermarkEntry = { text: localize('watermark.openFolder', "Open Folder"), id: 'workbench.action.files.openFolder', mac: false };
const openFileOrFolderMacOnly: WatermarkEntry = { text: localize('watermark.openFileFolder', "Open File or Folder"), id: 'workbench.action.files.openFileFolder', mac: true };
const openRecent: WatermarkEntry = { text: localize('watermark.openRecent', "Open Recent"), id: 'workbench.action.openRecent' };
const newUntitledFile: WatermarkEntry = { text: localize('watermark.newUntitledFile', "New Untitled Text File"), id: 'workbench.action.files.newUntitledFile' };
const newUntitledFileMacOnly: WatermarkEntry = Object.assign({ mac: true }, newUntitledFile);
const newUntitledFileMacOnly: WatermarkEntry = { text: localize('watermark.newUntitledFile', "New Untitled Text File"), id: 'workbench.action.files.newUntitledFile', mac: true };
const findInFiles: WatermarkEntry = { text: localize('watermark.findInFiles', "Find in Files"), id: 'workbench.action.findInFiles' };
const toggleTerminal: WatermarkEntry = { text: localize({ key: 'watermark.toggleTerminal', comment: ['toggle is a verb here'] }, "Toggle Terminal"), id: 'workbench.action.terminal.toggleTerminal', when: ContextKeyExpr.equals('terminalProcessSupported', true) };
const startDebugging: WatermarkEntry = { text: localize('watermark.startDebugging', "Start Debugging"), id: 'workbench.action.debug.start', when: ContextKeyExpr.equals('terminalProcessSupported', true) };
@@ -32,6 +32,9 @@ import { findGroup } from 'vs/workbench/services/editor/common/editorGroupFinder
import { SIDE_GROUP } from 'vs/workbench/services/editor/common/editorService';
import { IBoundarySashes } from 'vs/base/browser/ui/sash/sash';
import { IHostService } from 'vs/workbench/services/host/browser/host';
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
import { EditorPartMaximizedEditorGroupContext, EditorPartMultipleEditorGroupsContext } from 'vs/workbench/common/contextkeys';
interface IEditorPartUIState {
readonly serializedGrid: ISerializedGrid;
@@ -140,6 +143,8 @@ export class EditorPart extends Part implements IEditorPart, IEditorGroupsView {
private container: HTMLElement | undefined;
private scopedInstantiationService!: IInstantiationService;
private centeredLayoutWidget!: CenteredViewLayout;
private gridWidget!: SerializableGrid<IEditorGroupView>;
@@ -156,7 +161,8 @@ export class EditorPart extends Part implements IEditorPart, IEditorGroupsView {
@IConfigurationService private readonly configurationService: IConfigurationService,
@IStorageService storageService: IStorageService,
@IWorkbenchLayoutService layoutService: IWorkbenchLayoutService,
@IHostService private readonly hostService: IHostService
@IHostService private readonly hostService: IHostService,
@IContextKeyService private readonly contextKeyService: IContextKeyService
) {
super(id, { hasTitle: false }, themeService, storageService, layoutService);
@@ -214,7 +220,7 @@ export class EditorPart extends Part implements IEditorPart, IEditorGroupsView {
readonly sideGroup: IEditorSideGroup = {
openEditor: (editor, options) => {
const [group] = this.instantiationService.invokeFunction(accessor => findGroup(accessor, { editor, options }, SIDE_GROUP));
const [group] = this.scopedInstantiationService.invokeFunction(accessor => findGroup(accessor, { editor, options }, SIDE_GROUP));
return group.openEditor(editor, options);
}
@@ -624,11 +630,11 @@ export class EditorPart extends Part implements IEditorPart, IEditorGroupsView {
// Create group view
let groupView: IEditorGroupView;
if (from instanceof EditorGroupView) {
groupView = EditorGroupView.createCopy(from, this.editorPartsView, this, this.groupsLabel, this.count, this.instantiationService);
groupView = EditorGroupView.createCopy(from, this.editorPartsView, this, this.groupsLabel, this.count, this.scopedInstantiationService,);
} else if (isSerializedEditorGroupModel(from)) {
groupView = EditorGroupView.createFromSerialized(from, this.editorPartsView, this, this.groupsLabel, this.count, this.instantiationService);
groupView = EditorGroupView.createFromSerialized(from, this.editorPartsView, this, this.groupsLabel, this.count, this.scopedInstantiationService);
} else {
groupView = EditorGroupView.createNew(this.editorPartsView, this, this.groupsLabel, this.count, this.instantiationService);
groupView = EditorGroupView.createNew(this.editorPartsView, this, this.groupsLabel, this.count, this.scopedInstantiationService);
}
// Keep in map
@@ -930,7 +936,7 @@ export class EditorPart extends Part implements IEditorPart, IEditorGroupsView {
createEditorDropTarget(container: unknown, delegate: IEditorDropTargetDelegate): IDisposable {
assertType(container instanceof HTMLElement);
return this.instantiationService.createInstance(EditorDropTarget, container, delegate);
return this.scopedInstantiationService.createInstance(EditorDropTarget, container, delegate);
}
//#region Part
@@ -967,6 +973,12 @@ export class EditorPart extends Part implements IEditorPart, IEditorGroupsView {
this.container.classList.add('content');
parent.appendChild(this.container);
// Scoped instantiation service
const scopedContextKeyService = this._register(this.contextKeyService.createScoped(this.container));
this.scopedInstantiationService = this.instantiationService.createChild(new ServiceCollection(
[IContextKeyService, scopedContextKeyService]
));
// Grid control
this.doCreateGridControl(options);
@@ -977,6 +989,9 @@ export class EditorPart extends Part implements IEditorPart, IEditorGroupsView {
// Drag & Drop support
this.setupDragAndDropSupport(parent, this.container);
// Context keys
this.handleContextKeys(scopedContextKeyService);
// Signal ready
this.whenReadyPromise.complete();
this._isReady = true;
@@ -989,6 +1004,32 @@ export class EditorPart extends Part implements IEditorPart, IEditorGroupsView {
return this.container;
}
private handleContextKeys(contextKeyService: IContextKeyService): void {
const multipleEditorGroupsContext = EditorPartMultipleEditorGroupsContext.bindTo(contextKeyService);
const maximizedEditorGroupContext = EditorPartMaximizedEditorGroupContext.bindTo(contextKeyService);
const updateContextKeys = () => {
const groupCount = this.count;
if (groupCount > 1) {
multipleEditorGroupsContext.set(true);
} else {
multipleEditorGroupsContext.reset();
}
if (this.hasMaximizedGroup()) {
maximizedEditorGroupContext.set(true);
} else {
maximizedEditorGroupContext.reset();
}
};
updateContextKeys();
this._register(this.onDidAddGroup(() => updateContextKeys()));
this._register(this.onDidRemoveGroup(() => updateContextKeys()));
this._register(this.onDidChangeGroupMaximized(() => updateContextKeys()));
}
private setupDragAndDropSupport(parent: HTMLElement, container: HTMLElement): void {
// Editor drop target
@@ -1335,9 +1376,10 @@ export class MainEditorPart extends EditorPart {
@IConfigurationService configurationService: IConfigurationService,
@IStorageService storageService: IStorageService,
@IWorkbenchLayoutService layoutService: IWorkbenchLayoutService,
@IHostService hostService: IHostService
@IHostService hostService: IHostService,
@IContextKeyService contextKeyService: IContextKeyService
) {
super(editorPartsView, Parts.EDITOR_PART, '', false, instantiationService, themeService, configurationService, storageService, layoutService, hostService);
super(editorPartsView, Parts.EDITOR_PART, '', false, instantiationService, themeService, configurationService, storageService, layoutService, hostService, contextKeyService);
}
}
@@ -1356,10 +1398,11 @@ export class AuxiliaryEditorPart extends EditorPart implements IAuxiliaryEditorP
@IConfigurationService configurationService: IConfigurationService,
@IStorageService storageService: IStorageService,
@IWorkbenchLayoutService layoutService: IWorkbenchLayoutService,
@IHostService hostService: IHostService
@IHostService hostService: IHostService,
@IContextKeyService contextKeyService: IContextKeyService
) {
const id = AuxiliaryEditorPart.COUNTER++;
super(editorPartsView, `workbench.parts.auxiliaryEditor.${id}`, groupsLabel, true, instantiationService, themeService, configurationService, storageService, layoutService, hostService);
super(editorPartsView, `workbench.parts.auxiliaryEditor.${id}`, groupsLabel, true, instantiationService, themeService, configurationService, storageService, layoutService, hostService, contextKeyService);
}
protected override saveState(): void {
@@ -315,7 +315,6 @@ const nlsMultiSelection = localize('multiSelection', "{0} selections");
const nlsEOLLF = localize('endOfLineLineFeed', "LF");
const nlsEOLCRLF = localize('endOfLineCarriageReturnLineFeed', "CRLF");
export class EditorStatus extends Disposable implements IWorkbenchContribution {
private readonly tabFocusModeElement = this._register(new MutableDisposable<IStatusbarEntryAccessor>());
@@ -335,6 +334,7 @@ export class EditorStatus extends Disposable implements IWorkbenchContribution {
private toRender: StateChange | undefined = undefined;
private editorService: IEditorService;
private targetWindow = window;
constructor(
@IEditorService editorService: IEditorService,
@@ -570,7 +570,7 @@ export class EditorStatus extends Disposable implements IWorkbenchContribution {
if (toRender) {
this.doRenderNow();
}
});
}, this.targetWindow);
} else {
this.toRender.combine(changed);
}
@@ -77,7 +77,7 @@ export class EditorTitleControl extends Themable {
}
private createBreadcrumbsControl(): BreadcrumbsControlFactory | undefined {
if (this.groupsView.partOptions.showTabs !== 'multiple') {
if (this.groupsView.partOptions.showTabs === 'single') {
return undefined; // Single tabs have breadcrumbs inlined. No tabs have no breadcrumbs.
}
@@ -175,7 +175,7 @@ export class EditorTitleControl extends Themable {
// Update editor tabs control if options changed
if (
oldOptions.showTabs !== newOptions.showTabs ||
(newOptions.showTabs === 'multiple' && oldOptions.pinnedTabsOnSeparateRow !== newOptions.pinnedTabsOnSeparateRow)
(newOptions.showTabs !== 'single' && oldOptions.pinnedTabsOnSeparateRow !== newOptions.pinnedTabsOnSeparateRow)
) {
// Clear old
this.editorTabsControlDisposable.clear();
@@ -115,9 +115,9 @@
}
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink.has-icon.tab-actions-right,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink.has-icon.tab-actions-off:not(.sticky-compact),
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink.has-icon.close-action-off:not(.sticky-compact),
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-fixed.has-icon.tab-actions-right,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-fixed.has-icon.tab-actions-off:not(.sticky-compact) {
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-fixed.has-icon.close-action-off:not(.sticky-compact) {
padding-left: 5px; /* reduce padding when we show icons and are in shrinking mode and tab actions is not left (unless sticky-compact) */
}
@@ -205,9 +205,9 @@
}
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink.tab-actions-left::after,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink.tab-actions-off::after,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink.close-action-off::after,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-fixed.tab-actions-left::after,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-fixed.tab-actions-off::after {
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-fixed.close-action-off::after {
content: '';
display: flex;
flex: 0;
@@ -310,7 +310,7 @@
padding-right: 5px; /* with tab sizing shrink/fixed and badges, we want a right-padding because the close button is hidden */
}
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink:not(.tab-actions-left):not(.tab-actions-off) .tab-label {
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink:not(.tab-actions-left):not(.close-action-off) .tab-label {
padding-right: 5px; /* ensure that the gradient does not show when tab actions show https://github.com/microsoft/vscode/issues/189625*/
}
@@ -365,16 +365,16 @@
overflow: visible; /* ...but still show the tab actions on hover, focus and when dirty or sticky */
}
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.tab-actions-off:not(.dirty):not(.sticky) > .tab-actions,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.tab-actions-off.sticky-compact > .tab-actions {
display: none; /* hide the tab actions when we are configured to hide it (unless dirty or sticky, but always when sticky-compact) */
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.close-action-off:not(.dirty) > .tab-actions,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.close-action-off.sticky-compact > .tab-actions {
display: none; /* hide the tab actions when we are configured to hide it (unless dirty, but always when sticky-compact) */
}
.monaco-workbench .part.editor > .content .editor-group-container.active > .title .tabs-container > .tab.active > .tab-actions .action-label, /* always show tab actions for active tab */
.monaco-workbench .part.editor > .content .editor-group-container.active > .title .tabs-container > .tab > .tab-actions .action-label:focus, /* always show tab actions on focus */
.monaco-workbench .part.editor > .content .editor-group-container.active > .title .tabs-container > .tab:hover > .tab-actions .action-label, /* always show tab actions on hover */
.monaco-workbench .part.editor > .content .editor-group-container.active > .title .tabs-container > .tab.active:hover > .tab-actions .action-label, /* always show tab actions on hover */
.monaco-workbench .part.editor > .content .editor-group-container.active > .title .tabs-container > .tab.sticky > .tab-actions .action-label, /* always show tab actions for sticky tabs */
.monaco-workbench .part.editor > .content .editor-group-container.active > .title .tabs-container > .tab.sticky:not(.pinned-action-off) > .tab-actions .action-label, /* always show tab actions for sticky tabs */
.monaco-workbench .part.editor > .content .editor-group-container.active > .title .tabs-container > .tab.dirty > .tab-actions .action-label { /* always show tab actions for dirty tabs */
opacity: 1;
}
@@ -404,7 +404,7 @@
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.active > .tab-actions .action-label,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.active:hover > .tab-actions .action-label,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.dirty > .tab-actions .action-label,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sticky > .tab-actions .action-label,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sticky:not(.pinned-action-off) > .tab-actions .action-label,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab:hover > .tab-actions .action-label {
opacity: 0.5; /* show tab actions dimmed for inactive group */
}
@@ -415,25 +415,24 @@
/* Tab Actions: Off */
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.tab-actions-off {
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.close-action-off {
padding-right: 10px; /* give a little bit more room if tab actions is off */
}
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink.tab-actions-off:not(.sticky-compact),
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-fixed.tab-actions-off:not(.sticky-compact) {
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink.close-action-off:not(.sticky-compact),
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-fixed.close-action-off:not(.sticky-compact) {
padding-right: 5px; /* we need less room when sizing is shrink/fixed (unless tab is sticky-compact) */
}
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.tab-actions-off.dirty-border-top > .tab-actions {
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.close-action-off.dirty-border-top > .tab-actions {
display: none; /* hide dirty state when highlightModifiedTabs is enabled and when running without tab actions */
}
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.tab-actions-off.dirty:not(.dirty-border-top):not(.sticky-compact),
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.tab-actions-off.sticky:not(.sticky-compact) {
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.close-action-off.dirty:not(.dirty-border-top):not(.sticky-compact) {
padding-right: 0; /* remove extra padding when we are running without tab actions (unless tab is sticky-compact) */
}
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.tab-actions-off > .tab-actions {
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.close-action-off > .tab-actions {
pointer-events: none; /* don't allow tab actions to be clicked when running without tab actions */
}
@@ -745,7 +745,9 @@ export class MultiEditorTabsControl extends EditorTabsControl {
// Redraw tabs when other options change
if (
oldOptions.labelFormat !== newOptions.labelFormat ||
oldOptions.tabCloseButton !== newOptions.tabCloseButton ||
oldOptions.tabActionLocation !== newOptions.tabActionLocation ||
oldOptions.tabActionCloseVisibility !== newOptions.tabActionCloseVisibility ||
oldOptions.tabActionUnpinVisibility !== newOptions.tabActionUnpinVisibility ||
oldOptions.tabSizing !== newOptions.tabSizing ||
oldOptions.pinnedTabSizing !== newOptions.pinnedTabSizing ||
oldOptions.showIcons !== newOptions.showIcons ||
@@ -1036,7 +1038,7 @@ export class MultiEditorTabsControl extends EditorTabsControl {
// Fixes https://github.com/microsoft/vscode/issues/18733
tab.classList.add('dragged');
scheduleAtNextAnimationFrame(() => tab.classList.remove('dragged'));
scheduleAtNextAnimationFrame(() => tab.classList.remove('dragged'), getWindow(tab));
}));
// Drop support
@@ -1321,19 +1323,33 @@ export class MultiEditorTabsControl extends EditorTabsControl {
this.redrawTabLabel(editor, tabIndex, tabContainer, tabLabelWidget, tabLabel);
// Action
const tabAction = isTabSticky ? this.unpinEditorAction : this.closeEditorAction;
if (!tabActionBar.hasAction(tabAction)) {
const hasUnpinAction = isTabSticky && options.tabActionUnpinVisibility;
const hasCloseAction = !hasUnpinAction && options.tabActionCloseVisibility;
const hasAction = hasUnpinAction || hasCloseAction;
// If no action is visible, ensure to clear it
if (!hasAction) {
if (!tabActionBar.isEmpty()) {
tabActionBar.clear();
}
}
// If action is visible, ensure it is showing
else {
const tabAction = hasUnpinAction ? this.unpinEditorAction : this.closeEditorAction;
if (!tabActionBar.hasAction(tabAction)) {
if (!tabActionBar.isEmpty()) {
tabActionBar.clear();
}
tabActionBar.push(tabAction, { icon: true, label: false, keybinding: this.getKeybindingLabel(tabAction) });
tabActionBar.push(tabAction, { icon: true, label: false, keybinding: this.getKeybindingLabel(tabAction) });
}
}
// Settings
const tabActionsVisibility = isTabSticky && options.pinnedTabSizing === 'compact' ? 'off' /* treat sticky compact tabs as tabCloseButton: 'off' */ : options.tabCloseButton;
for (const option of ['off', 'left', 'right']) {
tabContainer.classList.toggle(`tab-actions-${option}`, tabActionsVisibility === option);
tabContainer.classList.toggle(`pinned-action-off`, isTabSticky && !hasUnpinAction);
tabContainer.classList.toggle(`close-action-off`, !hasUnpinAction && !hasCloseAction);
for (const option of ['left', 'right']) {
tabContainer.classList.toggle(`tab-actions-${option}`, hasAction && options.tabActionLocation === option);
}
const tabSizing = isTabSticky && options.pinnedTabSizing === 'shrink' ? 'shrink' /* treat sticky shrink tabs as tabSizing: 'shrink' */ : options.tabSizing;
@@ -1593,16 +1609,25 @@ export class MultiEditorTabsControl extends EditorTabsControl {
Object.assign(this.dimensions, dimensions);
if (this.visible) {
// The layout of tabs can be an expensive operation because we access DOM properties
// that can result in the browser doing a full page layout to validate them. To buffer
// this a little bit we try at least to schedule this work on the next animation frame
// when we have restored or when idle otherwise.
if (!this.layoutScheduler.value) {
const scheduledLayout = (this.lifecycleService.phase >= LifecyclePhase.Restored ? scheduleAtNextAnimationFrame : runWhenIdle)(() => {
// The layout of tabs can be an expensive operation because we access DOM properties
// that can result in the browser doing a full page layout to validate them. To buffer
// this a little bit we try at least to schedule this work on the next animation frame
// when we have restored or when idle otherwise.
const layoutFunction = () => {
this.doLayout(this.dimensions, this.layoutScheduler.value?.options /* ensure to pick up latest options */);
this.layoutScheduler.clear();
});
};
let scheduledLayout: IDisposable;
if (this.lifecycleService.phase >= LifecyclePhase.Restored) {
scheduledLayout = scheduleAtNextAnimationFrame(layoutFunction, getWindow(this.tabsContainer));
} else {
scheduledLayout = runWhenIdle(layoutFunction);
}
this.layoutScheduler.value = { options, dispose: () => scheduledLayout.dispose() };
}
@@ -11,6 +11,7 @@ import { IEditorTitleControlDimensions } from 'vs/workbench/browser/parts/editor
import { IToolbarActions } from 'vs/workbench/common/editor';
export class NoEditorTabsControl extends EditorTabsControl {
private activeEditor: EditorInput | null = null;
protected prepareEditorActions(editorActions: IToolbarActions): IToolbarActions {
return {
@@ -20,10 +21,27 @@ export class NoEditorTabsControl extends EditorTabsControl {
}
openEditor(editor: EditorInput): boolean {
return false;
return this.handleOpenedEditors();
}
openEditors(editors: EditorInput[]): boolean {
return this.handleOpenedEditors();
}
private handleOpenedEditors(): boolean {
const didChange = this.activeEditorChanged();
this.activeEditor = this.tabsModel.activeEditor;
return didChange;
}
private activeEditorChanged(): boolean {
if (
!this.activeEditor && this.tabsModel.activeEditor || // active editor changed from null => editor
this.activeEditor && !this.tabsModel.activeEditor || // active editor changed from editor => null
(!this.activeEditor || !this.tabsModel.isActive(this.activeEditor)) // active editor changed from editorA => editorB
) {
return true;
}
return false;
}
@@ -7,7 +7,7 @@ import 'vs/css!./media/notificationsToasts';
import { localize } from 'vs/nls';
import { INotificationsModel, NotificationChangeType, INotificationChangeEvent, INotificationViewItem, NotificationViewItemContentChangeKind } from 'vs/workbench/common/notifications';
import { IDisposable, dispose, toDisposable, DisposableStore } from 'vs/base/common/lifecycle';
import { addDisposableListener, EventType, Dimension, scheduleAtNextAnimationFrame, isAncestorOfActiveElement } from 'vs/base/browser/dom';
import { addDisposableListener, EventType, Dimension, scheduleAtNextAnimationFrame, isAncestorOfActiveElement, getWindow } from 'vs/base/browser/dom';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { NotificationsList } from 'vs/workbench/browser/parts/notifications/notificationsList';
import { Event, Emitter } from 'vs/base/common/event';
@@ -150,7 +150,7 @@ export class NotificationsToasts extends Themable implements INotificationsToast
// (see also https://github.com/microsoft/vscode/issues/107935)
const itemDisposables = new DisposableStore();
this.mapNotificationToDisposable.set(item, itemDisposables);
itemDisposables.add(scheduleAtNextAnimationFrame(() => this.doAddToast(item, itemDisposables)));
itemDisposables.add(scheduleAtNextAnimationFrame(() => this.doAddToast(item, itemDisposables), getWindow(this.container)));
}
private doAddToast(item: INotificationViewItem, itemDisposables: DisposableStore): void {
@@ -24,7 +24,7 @@ import { CustomMenubarControl } from 'vs/workbench/browser/parts/titlebar/menuba
import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
import { Emitter, Event } from 'vs/base/common/event';
import { IStorageService } from 'vs/platform/storage/common/storage';
import { Parts, IWorkbenchLayoutService, LayoutSettings, ActivityBarPosition } from 'vs/workbench/services/layout/browser/layoutService';
import { Parts, IWorkbenchLayoutService, ActivityBarPosition, LayoutSettings } from 'vs/workbench/services/layout/browser/layoutService';
import { createActionViewItem, createAndFillInActionBarActions } from 'vs/platform/actions/browser/menuEntryActionViewItem';
import { Action2, IMenu, IMenuService, MenuId, registerAction2 } from 'vs/platform/actions/common/actions';
import { ContextKeyExpr, ContextKeyExpression, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
@@ -54,8 +54,6 @@ import { IEditorCommandsContext, IToolbarActions } from 'vs/workbench/common/edi
export class TitlebarPart extends Part implements ITitleService {
private static readonly configCommandCenter = 'window.commandCenter';
declare readonly _serviceBrand: undefined;
//#region IView
@@ -159,7 +157,7 @@ export class TitlebarPart extends Part implements ITitleService {
}
get isCommandCenterVisible() {
return this.configurationService.getValue<boolean>(TitlebarPart.configCommandCenter);
return this.configurationService.getValue<boolean>(LayoutSettings.COMMAND_CENTER);
}
private registerListeners(): void {
@@ -202,7 +200,7 @@ export class TitlebarPart extends Part implements ITitleService {
}
}
if (event.affectsConfiguration(TitlebarPart.configCommandCenter)) {
if (event.affectsConfiguration(LayoutSettings.COMMAND_CENTER)) {
this.updateTitle();
this._onDidChangeCommandCenterVisibility.fire();
this._onDidChange.fire(undefined);
@@ -640,7 +638,7 @@ class ToogleConfigAction extends Action2 {
registerAction2(class ToogleCommandCenter extends ToogleConfigAction {
constructor() {
super('window.commandCenter', localize('toggle.commandCenter', 'Command Center'), 1);
super(LayoutSettings.COMMAND_CENTER, localize('toggle.commandCenter', 'Command Center'), 1);
}
});
@@ -11,7 +11,7 @@ import { ConfigurationMigrationWorkbenchContribution, DynamicWorkbenchConfigurat
import { isStandalone } from 'vs/base/browser/browser';
import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions } from 'vs/workbench/common/contributions';
import { LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle';
import { ActivityBarPosition, LayoutSettings } from 'vs/workbench/services/layout/browser/layoutService';
import { ActivityBarPosition, EditorTabsMode, LayoutSettings } from 'vs/workbench/services/layout/browser/layoutService';
const registry = Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Configuration);
@@ -38,9 +38,9 @@ const registry = Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Con
description: localize('tabScrollbarHeight', "Controls the height of the scrollbars used for tabs and breadcrumbs in the editor title area."),
default: 'default',
},
'workbench.editor.showTabs': {
[LayoutSettings.EDITOR_TABS_MODE]: {
'type': 'string',
'enum': ['multiple', 'single', 'none'],
'enum': [EditorTabsMode.MULTIPLE, EditorTabsMode.SINGLE, EditorTabsMode.NONE],
'enumDescriptions': [
localize('workbench.editor.showTabs.multiple', "Each editor is displayed as a tab in the editor title area."),
localize('workbench.editor.showTabs.single', "The active editor is displayed as a single large tab in the editor title area."),
@@ -153,11 +153,21 @@ const registry = Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Con
}
}
},
'workbench.editor.tabCloseButton': {
'type': 'string',
'enum': ['left', 'right', 'off'],
'default': 'right',
'markdownDescription': localize({ comment: ['This is the description for a setting. Values surrounded by single quotes are not to be translated.'], key: 'editorTabCloseButton' }, "Controls the position of the editor's tabs close buttons, or disables them when set to 'off'. This value is ignored when `#workbench.editor.showTabs#` is not set to `multiple`.")
'workbench.editor.tabActionLocation': {
type: 'string',
enum: ['left', 'right'],
default: 'right',
markdownDescription: localize({ comment: ['This is the description for a setting. Values surrounded by single quotes are not to be translated.'], key: 'tabActionLocation' }, "Controls the position of the editor's tabs action buttons (close, unpin). This value is ignored when `#workbench.editor.showTabs#` is not set to `multiple`.")
},
'workbench.editor.tabActionCloseVisibility': {
type: 'boolean',
default: true,
description: localize('workbench.editor.tabActionCloseVisibility', "Controls the visibility of the tab close action button.")
},
'workbench.editor.tabActionUnpinVisibility': {
type: 'boolean',
default: true,
description: localize('workbench.editor.tabActionUnpinVisibility', "Controls the visibility of the tab unpin action button.")
},
'workbench.editor.tabSizing': {
'type': 'string',
@@ -632,7 +642,7 @@ const registry = Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Con
'default': isMacintosh ? ' \u2014 ' : ' - ',
'markdownDescription': localize("window.titleSeparator", "Separator used by {0}.", '`#window.title#`')
},
'window.commandCenter': {
[LayoutSettings.COMMAND_CENTER]: {
type: 'boolean',
default: true,
markdownDescription: isWeb ?
@@ -806,11 +816,21 @@ Registry.as<IConfigurationMigrationRegistry>(Extensions.ConfigurationMigration)
return [['workbench.editor.doubleClickTabToToggleEditorGroupSizes', { value: value }]];
}
}, {
key: 'workbench.editor.showTabs', migrateFn: (value: any) => {
key: LayoutSettings.EDITOR_TABS_MODE, migrateFn: (value: any) => {
if (typeof value === 'boolean') {
value = value ? 'multiple' : 'single';
value = value ? EditorTabsMode.MULTIPLE : EditorTabsMode.SINGLE;
}
return [['workbench.editor.showTabs', { value: value }]];
return [[LayoutSettings.EDITOR_TABS_MODE, { value }]];
}
}, {
key: 'workbench.editor.tabCloseButton', migrateFn: (value: any) => {
const result: ConfigurationKeyValuePairs = [];
if (value === 'left' || value === 'right') {
result.push(['workbench.editor.tabActionLocation', { value }]);
} else if (value === 'off') {
result.push(['workbench.editor.tabActionCloseVisibility', { value: false }]);
}
return result;
}
}, {
key: 'zenMode.hideTabs', migrateFn: (value: any) => {
+5 -1
View File
@@ -71,6 +71,11 @@ export const ActiveEditorGroupLockedContext = new RawContextKey<boolean>('active
export const MultipleEditorGroupsContext = new RawContextKey<boolean>('multipleEditorGroups', false, localize('multipleEditorGroups', "Whether there are multiple editor groups opened"));
export const SingleEditorGroupsContext = MultipleEditorGroupsContext.toNegated();
// Editor Part Context Keys
export const EditorPartMultipleEditorGroupsContext = new RawContextKey<boolean>('editorPartMultipleEditorGroups', false, localize('editorPartMultipleEditorGroups', "Whether there are multiple editor groups opened in an editor part"));
export const EditorPartSingleEditorGroupsContext = EditorPartMultipleEditorGroupsContext.toNegated();
export const EditorPartMaximizedEditorGroupContext = new RawContextKey<boolean>('editorPartMaximizedEditorGroup', false, localize('editorPartEditorGroupMaximized', "Editor Part has a maximized group"));
// Editor Layout Context Keys
export const EditorsVisibleContext = new RawContextKey<boolean>('editorIsOpen', false, localize('editorIsOpen', "Whether an editor is open"));
export const InEditorZenModeContext = new RawContextKey<boolean>('inZenMode', false, localize('inZenMode', "Whether Zen mode is enabled"));
@@ -79,7 +84,6 @@ export const SplitEditorsVertically = new RawContextKey<boolean>('splitEditorsVe
export const EditorAreaVisibleContext = new RawContextKey<boolean>('editorAreaVisible', true, localize('editorAreaVisible', "Whether the editor area is visible"));
export const EditorTabsVisibleContext = new RawContextKey<boolean>('editorTabsVisible', true, localize('editorTabsVisible', "Whether editor tabs are visible"));
export const EditorPinnedAndUnpinnedTabsContext = new RawContextKey<boolean>('editorPinnedAndUnpinnedTabsVisible', false, true);
export const MaximizedEditorGroupContext = new RawContextKey<boolean>('maximizedEditorGroup', false, localize('editorGroupMaximized', "Editor group is maximized"));
//#endregion
+3 -1
View File
@@ -1113,7 +1113,9 @@ interface IEditorPartConfiguration {
wrapTabs?: boolean;
scrollToSwitchTabs?: boolean;
highlightModifiedTabs?: boolean;
tabCloseButton?: 'left' | 'right' | 'off';
tabActionLocation?: 'left' | 'right';
tabActionCloseVisibility?: boolean;
tabActionUnpinVisibility?: boolean;
tabSizing?: 'fit' | 'shrink' | 'fixed';
tabSizingFixedMinWidth?: number;
tabSizingFixedMaxWidth?: number;
@@ -458,7 +458,7 @@ export class ChatListItemRenderer extends Disposable implements ITreeRenderer<Ch
const disposable = templateData.elementDisposables.add(dom.scheduleAtNextAnimationFrame(() => {
disposable.dispose();
this._onDidChangeItemHeight.fire({ element, height: newHeight });
}));
}, dom.getWindow(templateData.value)));
}
}
@@ -496,7 +496,7 @@ export class ChatListItemRenderer extends Disposable implements ITreeRenderer<Ch
const disposable = templateData.elementDisposables.add(dom.scheduleAtNextAnimationFrame(() => {
disposable.dispose();
this._onDidChangeItemHeight.fire({ element, height: newHeight });
}));
}, dom.getWindow(templateData.value)));
}
}
@@ -74,6 +74,12 @@ export class QuickChatService extends Disposable implements IQuickChatService {
open(providerId?: string, options?: IQuickChatOpenOptions): void {
if (this._input) {
if (this._currentChat && options?.query) {
this._currentChat.setValue(options.query, options.selection);
if (!options.isPartialQuery) {
this._currentChat.acceptInput();
}
}
return this.focus();
}
@@ -407,7 +407,7 @@ export class ChatWidget extends Disposable implements IChatWidget {
dom.scheduleAtNextAnimationFrame(() => {
// Can't set scrollTop during this event listener, the list might overwrite the change
revealLastElement(this.tree);
}, 0);
}, dom.getWindow(this.listContainer), 0);
}
}
@@ -640,7 +640,7 @@ export class ChatWidget extends Disposable implements IChatWidget {
const inputPartHeight = this.inputPart.layout(possibleMaxHeight, width);
const newHeight = Math.min(renderHeight + diff, possibleMaxHeight - inputPartHeight);
this.layout(newHeight + inputPartHeight, width);
});
}, dom.getWindow(this.listContainer));
}));
}
@@ -89,7 +89,7 @@ class InputEditorDecorations extends Disposable {
private registerViewModelListeners(): void {
this.viewModelDisposables.value = this.widget.viewModel?.onDidChange(e => {
if (e?.kind === 'changePlaceholder') {
if (e?.kind === 'changePlaceholder' || e?.kind === 'initialize') {
this.updateInputEditorDecorations();
}
});
@@ -127,7 +127,6 @@ class InputEditorDecorations extends Disposable {
private async updateInputEditorDecorations() {
const inputValue = this.widget.inputEditor.getValue();
const slashCommands = await this.widget.getSlashCommands(); // TODO this async call can lead to a flicker of the placeholder text when switching editor tabs
const viewModel = this.widget.viewModel;
if (!viewModel) {
@@ -136,10 +135,7 @@ class InputEditorDecorations extends Disposable {
if (!inputValue) {
const viewModelPlaceholder = this.widget.viewModel?.inputPlaceholder;
const defaultPlaceholder = slashCommands?.length ?
localize('interactive.input.placeholderWithCommands', "Ask a question or type '@' or '/'") :
localize('interactive.input.placeholderNoCommands', "Ask a question");
const placeholder = viewModelPlaceholder ?? defaultPlaceholder;
const placeholder = viewModelPlaceholder ?? '';
const decoration: IDecorationOptions[] = [
{
range: {
@@ -109,7 +109,7 @@
}
.interactive-item-container .header .avatar .codicon {
color: var(--vscode-chat-avatarForeground);
color: var(--vscode-chat-avatarForeground) !important;
font-size: 14px;
}
@@ -15,13 +15,13 @@ export const chatRequestBorder = registerColor(
export const chatSlashCommandBackground = registerColor(
'chat.slashCommandBackground',
{ dark: badgeBackground, light: badgeBackground, hcDark: Color.white, hcLight: badgeBackground },
{ dark: '#34414B', light: '#D2ECFF', hcDark: Color.white, hcLight: badgeBackground },
localize('chat.slashCommandBackground', 'The background color of a chat slash command.')
);
export const chatSlashCommandForeground = registerColor(
'chat.slashCommandForeground',
{ dark: badgeForeground, light: badgeForeground, hcDark: Color.black, hcLight: badgeForeground },
{ dark: '#40A6FF', light: '#306CA2', hcDark: Color.black, hcLight: badgeForeground },
localize('chat.slashCommandForeground', 'The foreground color of a chat slash command.')
);
@@ -26,7 +26,7 @@ export function isWelcomeVM(item: unknown): item is IChatWelcomeMessageViewModel
return !!item && typeof item === 'object' && 'content' in item;
}
export type IChatViewModelChangeEvent = IChatAddRequestEvent | IChangePlaceholderEvent | null;
export type IChatViewModelChangeEvent = IChatAddRequestEvent | IChangePlaceholderEvent | IChatSessionInitEvent | null;
export interface IChatAddRequestEvent {
kind: 'addRequest';
@@ -36,6 +36,10 @@ export interface IChangePlaceholderEvent {
kind: 'changePlaceholder';
}
export interface IChatSessionInitEvent {
kind: 'initialize';
}
export interface IChatViewModel {
readonly initState: ChatModelInitState;
readonly providerId: string;
@@ -184,7 +188,10 @@ export class ChatViewModel extends Disposable implements IChatViewModel {
}
}
this._onDidChange.fire(e.kind === 'addRequest' ? { kind: 'addRequest' } : null);
const modelEventToVmEvent: IChatViewModelChangeEvent = e.kind === 'addRequest' ? { kind: 'addRequest' } :
e.kind === 'initialize' ? { kind: 'initialize' } :
null;
this._onDidChange.fire(modelEventToVmEvent);
}));
}
@@ -27,7 +27,7 @@ import { ISashEvent, IVerticalSashLayoutProvider, Orientation, Sash } from 'vs/b
import { registerColor } from 'vs/platform/theme/common/colorRegistry';
const NLS_FIND_INPUT_LABEL = nls.localize('label.find', "Find");
const NLS_FIND_INPUT_PLACEHOLDER = nls.localize('placeholder.find', "Find (\u21C5 for history)");
const NLS_FIND_INPUT_PLACEHOLDER = nls.localize('placeholder.find', "Find");
const NLS_PREVIOUS_MATCH_BTN_LABEL = nls.localize('label.previousMatchButton', "Previous Match");
const NLS_NEXT_MATCH_BTN_LABEL = nls.localize('label.nextMatchButton', "Next Match");
const NLS_CLOSE_BTN_LABEL = nls.localize('label.closeButton', "Close");
@@ -170,7 +170,7 @@ export class CommentNode<T extends IRange | ICellRange> extends Disposable {
this._scrollable = new Scrollable({
forceIntegerValues: true,
smoothScrollDuration: 125,
scheduleAtNextAnimationFrame: cb => dom.scheduleAtNextAnimationFrame(cb)
scheduleAtNextAnimationFrame: cb => dom.scheduleAtNextAnimationFrame(cb, dom.getWindow(container))
});
this._scrollableElement = this._register(new SmoothScrollableElement(body, {
horizontal: ScrollbarVisibility.Visible,
@@ -489,7 +489,7 @@ export class CommentNode<T extends IRange | ICellRange> extends Disposable {
dom.scheduleAtNextAnimationFrame(() => {
this._commentEditor!.layout({ width: container.clientWidth - 14, height: this._editorHeight });
this._commentEditor!.focus();
});
}, dom.getWindow(editContainer));
const lastLine = this._commentEditorModel.getLineCount();
const lastColumn = this._commentEditorModel.getLineLength(lastLine) + 1;
@@ -869,8 +869,20 @@ export class CommentController implements IEditorContribution {
const matchedZones = this._commentWidgets.filter(zoneWidget => zoneWidget.owner === thread.owner && Range.lift(zoneWidget.commentThread.range)?.equalsRange(thread.range));
if (thread.isReply && matchedZones.length) {
this.commentService.removeContinueOnComment({ owner: thread.owner, uri: editorURI, range: thread.range, isReply: true });
const matchedZone = matchedZones[0];
matchedZone.setPendingComment(thread.body);
matchedZones[0].setPendingComment(thread.body);
} else if (matchedZones.length) {
this.commentService.removeContinueOnComment({ owner: thread.owner, uri: editorURI, range: thread.range, isReply: false });
const existingPendingComment = matchedZones[0].getPendingComments().newComment;
// We need to try to reconcile the existing pending comment with the incoming pending comment
let pendingComment: string;
if (!existingPendingComment || thread.body.includes(existingPendingComment)) {
pendingComment = thread.body;
} else if (existingPendingComment.includes(thread.body)) {
pendingComment = existingPendingComment;
} else {
pendingComment = `${existingPendingComment}\n${thread.body}`;
}
matchedZones[0].setPendingComment(pendingComment);
} else if (!thread.isReply) {
const threadStillAvailable = this.commentService.removeContinueOnComment({ owner: thread.owner, uri: editorURI, range: thread.range, isReply: false });
if (!threadStillAvailable) {
@@ -36,7 +36,7 @@ import { debugToolBarBackground, debugToolBarBorder } from 'vs/workbench/contrib
import { CONTINUE_ID, CONTINUE_LABEL, DISCONNECT_AND_SUSPEND_ID, DISCONNECT_AND_SUSPEND_LABEL, DISCONNECT_ID, DISCONNECT_LABEL, FOCUS_SESSION_ID, FOCUS_SESSION_LABEL, PAUSE_ID, PAUSE_LABEL, RESTART_LABEL, RESTART_SESSION_ID, REVERSE_CONTINUE_ID, STEP_BACK_ID, STEP_INTO_ID, STEP_INTO_LABEL, STEP_OUT_ID, STEP_OUT_LABEL, STEP_OVER_ID, STEP_OVER_LABEL, STOP_ID, STOP_LABEL } from 'vs/workbench/contrib/debug/browser/debugCommands';
import * as icons from 'vs/workbench/contrib/debug/browser/debugIcons';
import { CONTEXT_DEBUG_STATE, CONTEXT_FOCUSED_SESSION_IS_ATTACH, CONTEXT_IN_DEBUG_MODE, CONTEXT_MULTI_SESSION_DEBUG, CONTEXT_STEP_BACK_SUPPORTED, CONTEXT_SUSPEND_DEBUGGEE_SUPPORTED, CONTEXT_TERMINATE_DEBUGGEE_SUPPORTED, IDebugConfiguration, IDebugService, State, VIEWLET_ID } from 'vs/workbench/contrib/debug/common/debug';
import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService';
import { EditorTabsMode, IWorkbenchLayoutService, LayoutSettings, Parts } from 'vs/workbench/services/layout/browser/layoutService';
import { Codicon } from 'vs/base/common/codicons';
const DEBUG_TOOLBAR_POSITION_KEY = 'debug.actionswidgetposition';
@@ -132,6 +132,10 @@ export class DebugToolBar extends Themable implements IWorkbenchContribution {
if (e.affectsConfiguration('debug.toolBarLocation')) {
this.updateScheduler.schedule();
}
if (e.affectsConfiguration(LayoutSettings.EDITOR_TABS_MODE) || e.affectsConfiguration(LayoutSettings.COMMAND_CENTER)) {
this._yRange = undefined;
this.setYCoordinate();
}
}));
this._register(this.debugToolBarMenu.onDidChange(() => this.updateScheduler.schedule()));
this._register(this.actionBar.actionRunner.onDidRun((e: IRunEvent) => {
@@ -163,7 +167,7 @@ export class DebugToolBar extends Themable implements IWorkbenchContribution {
// Prevent default to stop editor selecting text #8524
mouseMoveEvent.preventDefault();
// Reduce x by width of drag handle to reduce jarring #16604
this.setCoordinates(mouseMoveEvent.posx - 14, mouseMoveEvent.posy - (this.layoutService.mainContainerOffset.top));
this.setCoordinates(mouseMoveEvent.posx - 14, mouseMoveEvent.posy - 14);
});
const mouseUpListener = dom.addDisposableGenericMouseUpListener(window, (e: MouseEvent) => {
@@ -185,6 +189,11 @@ export class DebugToolBar extends Themable implements IWorkbenchContribution {
const position = parseFloat(left) / window.innerWidth;
this.storageService.store(DEBUG_TOOLBAR_POSITION_KEY, position, StorageScope.PROFILE, StorageTarget.MACHINE);
}
if (this.yCoordinate) {
this.storageService.store(DEBUG_TOOLBAR_Y_KEY, this.yCoordinate, StorageScope.PROFILE, StorageTarget.MACHINE);
} else {
this.storageService.remove(DEBUG_TOOLBAR_Y_KEY, StorageScope.PROFILE);
}
}
override updateStyles(): void {
@@ -208,12 +217,6 @@ export class DebugToolBar extends Themable implements IWorkbenchContribution {
}
}
private setYCoordinate(y = this.yCoordinate): void {
const titlebarOffset = this.layoutService.mainContainerOffset.top;
this.$el.style.top = `${titlebarOffset + y}px`;
this.yCoordinate = y;
}
private setCoordinates(x?: number, y?: number): void {
if (!this.isVisible) {
return;
@@ -230,12 +233,38 @@ export class DebugToolBar extends Themable implements IWorkbenchContribution {
if (y === undefined) {
y = this.storageService.getNumber(DEBUG_TOOLBAR_Y_KEY, StorageScope.PROFILE, 0);
}
const titleAreaHeight = 35;
if ((y < titleAreaHeight / 2) || (y > titleAreaHeight + titleAreaHeight / 2)) {
const moveToTop = y < titleAreaHeight;
this.setYCoordinate(moveToTop ? 0 : titleAreaHeight);
this.storageService.store(DEBUG_TOOLBAR_Y_KEY, moveToTop ? 0 : 2 * titleAreaHeight, StorageScope.PROFILE, StorageTarget.MACHINE);
this.setYCoordinate(y);
}
private setYCoordinate(y = this.yCoordinate): void {
const [yMin, yMax] = this.yRange;
y = Math.max(yMin, Math.min(y, yMax));
this.$el.style.top = `${y}px`;
this.yCoordinate = y;
}
private _yRange: [number, number] | undefined;
private get yRange(): [number, number] {
if (!this._yRange) {
const isTitleBarVisible = this.layoutService.isVisible(Parts.TITLEBAR_PART);
const yMin = isTitleBarVisible ? 0 : this.layoutService.mainContainerOffset.top;
let yMax = 0;
if (isTitleBarVisible) {
if (this.configurationService.getValue(LayoutSettings.COMMAND_CENTER) === true) {
yMax += 35;
} else {
yMax += 28;
}
}
if (this.configurationService.getValue(LayoutSettings.EDITOR_TABS_MODE) !== EditorTabsMode.NONE) {
yMax += 35;
}
this._yRange = [yMin, yMax];
}
return this._yRange;
}
private show(): void {
@@ -5,11 +5,12 @@
.monaco-workbench .debug-toolbar {
position: absolute;
z-index: 39;
height: 32px;
z-index: 3000;
height: 26px;
display: flex;
padding-left: 7px;
border-radius: 4px;
-webkit-app-region: no-drag;
}
.monaco-workbench .debug-toolbar .monaco-action-bar .action-item {
@@ -95,7 +95,7 @@ export class InteractiveEditorInput extends EditorInput implements ICompositeNot
@INotebookService private readonly _notebookService: INotebookService,
@IFileDialogService private readonly _fileDialogService: IFileDialogService
) {
const input = NotebookEditorInput.create(instantiationService, resource, 'interactive', {});
const input = NotebookEditorInput.getOrCreate(instantiationService, resource, undefined, 'interactive', {});
super();
this._notebookEditorInput = input;
this._register(this._notebookEditorInput);
@@ -998,7 +998,7 @@ export class DeletedElement extends SingleSideDiffElement {
}
this.layoutNotebookCell();
});
}, DOM.getWindow(this._diffEditorContainer));
}
_buildOutputRendererContainer() {
@@ -1201,7 +1201,7 @@ export class InsertElement extends SingleSideDiffElement {
if (this._diagonalFill) {
this._diagonalFill.style.height = `${this.cell.layoutInfo.editorHeight + this.cell.layoutInfo.editorMargin + this.cell.layoutInfo.metadataStatusHeight + this.cell.layoutInfo.metadataHeight + this.cell.layoutInfo.outputTotalHeight + this.cell.layoutInfo.outputStatusHeight}px`;
}
});
}, DOM.getWindow(this._diffEditorContainer));
}
override dispose() {
@@ -1626,7 +1626,7 @@ export class ModifiedElement extends AbstractElementRenderer {
}
this.layoutNotebookCell();
});
}, DOM.getWindow(this._diffEditorContainer));
}
override dispose() {
@@ -463,7 +463,7 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD
return diffElement.original;
}, DiffSide.Original);
}
});
}, DOM.getWindow(this._listViewContainer));
};
this._localStore.add(this._list.onDidChangeContentHeight(() => {
@@ -763,7 +763,7 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD
DOM.scheduleAtNextAnimationFrame(() => {
webview?.ackHeight([{ cellId: cellInfo.cellId, outputId, height }]);
}, 10);
}, DOM.getWindow(this._listViewContainer), 10);
}
private pendingLayouts = new WeakMap<DiffElementViewModelBase, IDisposable>();
@@ -784,7 +784,7 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD
relayout(cell, height);
r();
});
}, DOM.getWindow(this._listViewContainer));
this.pendingLayouts.set(cell, toDisposable(() => {
layoutDisposable.dispose();
@@ -114,7 +114,7 @@ export class NotebookDiffOverviewRuler extends Themable {
private _scheduleRender(): void {
if (this._renderAnimationFrame === null) {
this._renderAnimationFrame = DOM.runAtThisOrScheduleAtNextAnimationFrame(this._onRenderScheduled.bind(this), 16);
this._renderAnimationFrame = DOM.runAtThisOrScheduleAtNextAnimationFrame(this._onRenderScheduled.bind(this), DOM.getWindow(this._domNode.domNode), 16);
}
}
@@ -180,7 +180,7 @@ class NotebookDiffEditorSerializer implements IEditorSerializer {
}
}
type SerializedNotebookEditorData = { resource: URI; viewType: string; options?: NotebookEditorInputOptions };
type SerializedNotebookEditorData = { resource: URI; preferredResource: URI; viewType: string; options?: NotebookEditorInputOptions };
class NotebookEditorSerializer implements IEditorSerializer {
canSerialize(): boolean {
return true;
@@ -189,6 +189,7 @@ class NotebookEditorSerializer implements IEditorSerializer {
assertType(input instanceof NotebookEditorInput);
const data: SerializedNotebookEditorData = {
resource: input.resource,
preferredResource: input.preferredResource,
viewType: input.viewType,
options: input.options
};
@@ -199,12 +200,12 @@ class NotebookEditorSerializer implements IEditorSerializer {
if (!data) {
return undefined;
}
const { resource, viewType, options } = data;
const { resource, preferredResource, viewType, options } = data;
if (!data || !URI.isUri(resource) || typeof viewType !== 'string') {
return undefined;
}
const input = NotebookEditorInput.create(instantiationService, resource, viewType, options);
const input = NotebookEditorInput.getOrCreate(instantiationService, resource, preferredResource, viewType, options);
return input;
}
}
@@ -639,7 +640,7 @@ class SimpleNotebookWorkingCopyEditorHandler extends Disposable implements IWork
}
createEditor(workingCopy: IWorkingCopyIdentifier): EditorInput {
return NotebookEditorInput.create(this._instantiationService, workingCopy.resource, this._getViewType(workingCopy)!);
return NotebookEditorInput.getOrCreate(this._instantiationService, workingCopy.resource, undefined, this._getViewType(workingCopy)!);
}
private async _installHandler(): Promise<void> {
@@ -1454,7 +1454,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditorD
this._localStore.add(DOM.scheduleAtNextAnimationFrame(() => {
hasPendingChangeContentHeight = false;
this._updateScrollHeight();
}, 100));
}, DOM.getWindow(this._body), 100));
}));
this._localStore.add(this._list.onDidRemoveOutputs(outputs => {
@@ -2259,7 +2259,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditorD
};
if (this._list.inRenderingTransaction) {
const layoutDisposable = DOM.scheduleAtNextAnimationFrame(doLayout);
const layoutDisposable = DOM.scheduleAtNextAnimationFrame(doLayout, DOM.getWindow(this._body));
this._pendingLayouts?.set(cell, toDisposable(() => {
layoutDisposable.dispose();
@@ -2973,7 +2973,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditorD
this._webview?.ackHeight([...this._pendingOutputHeightAcks.values()]);
this._pendingOutputHeightAcks.clear();
}, -1); // -1 priority because this depends on calls to layoutNotebookCell, and that may be called multiple times before this runs
}, DOM.getWindow(this._body), -1); // -1 priority because this depends on calls to layoutNotebookCell, and that may be called multiple times before this runs
}
}
@@ -42,6 +42,7 @@ import { DiffEditorInputFactoryFunction, EditorInputFactoryFunction, EditorInput
import { IExtensionService, isProposedApiEnabled } from 'vs/workbench/services/extensions/common/extensions';
import { IExtensionPointUser } from 'vs/workbench/services/extensions/common/extensionsRegistry';
import { InstallRecommendedExtensionAction } from 'vs/workbench/contrib/extensions/browser/extensionsActions';
import { IUriIdentityService } from 'vs/platform/uriIdentity/common/uriIdentity';
export class NotebookProviderInfoStore extends Disposable {
@@ -62,7 +63,8 @@ export class NotebookProviderInfoStore extends Disposable {
@IAccessibilityService private readonly _accessibilityService: IAccessibilityService,
@IInstantiationService private readonly _instantiationService: IInstantiationService,
@IFileService private readonly _fileService: IFileService,
@INotebookEditorModelResolverService private readonly _notebookEditorModelResolverService: INotebookEditorModelResolverService
@INotebookEditorModelResolverService private readonly _notebookEditorModelResolverService: INotebookEditorModelResolverService,
@IUriIdentityService private readonly uriIdentService: IUriIdentityService,
) {
super();
@@ -178,12 +180,18 @@ export class NotebookProviderInfoStore extends Disposable {
};
const notebookEditorInputFactory: EditorInputFactoryFunction = ({ resource, options }) => {
const data = CellUri.parse(resource);
let notebookUri: URI = resource;
let notebookUri: URI;
let cellOptions: IResourceEditorInput | undefined;
let preferredResource = resource;
if (data) {
notebookUri = data.notebook;
// resource is a notebook cell
notebookUri = this.uriIdentService.asCanonicalUri(data.notebook);
preferredResource = data.notebook;
cellOptions = { resource, options };
} else {
notebookUri = this.uriIdentService.asCanonicalUri(resource);
}
if (!cellOptions) {
@@ -191,8 +199,10 @@ export class NotebookProviderInfoStore extends Disposable {
}
const notebookOptions = { ...options, cellOptions } as INotebookEditorOptions;
return { editor: NotebookEditorInput.create(this._instantiationService, notebookUri, notebookProviderInfo.id), options: notebookOptions };
const editor = NotebookEditorInput.getOrCreate(this._instantiationService, notebookUri, preferredResource, notebookProviderInfo.id);
return { editor, options: notebookOptions };
};
const notebookUntitledEditorFactory: UntitledEditorInputFactoryFunction = async ({ resource, options }) => {
const ref = await this._notebookEditorModelResolverService.resolve({ untitledResource: resource }, notebookProviderInfo.id);
@@ -202,7 +212,7 @@ export class NotebookProviderInfoStore extends Disposable {
ref!.dispose();
});
return { editor: NotebookEditorInput.create(this._instantiationService, ref.object.resource, notebookProviderInfo.id), options };
return { editor: NotebookEditorInput.getOrCreate(this._instantiationService, ref.object.resource, undefined, notebookProviderInfo.id), options };
};
const notebookDiffEditorInputFactory: DiffEditorInputFactoryFunction = ({ modified, original, label, description }) => {
return { editor: NotebookDiffEditorInput.create(this._instantiationService, modified.resource!, label, description, original.resource!, notebookProviderInfo.id) };
@@ -128,18 +128,19 @@ export class CellPartsCollection extends Disposable {
private _scheduledOverlayUpdateExecutionState = this._register(new MutableDisposable());
constructor(
private readonly targetWindow: Window,
private readonly contentParts: readonly CellContentPart[],
private readonly overlayParts: readonly CellOverlayPart[]
) {
super();
}
concatContentPart(other: readonly CellContentPart[]): CellPartsCollection {
return new CellPartsCollection(this.contentParts.concat(other), this.overlayParts);
concatContentPart(other: readonly CellContentPart[], targetWindow: Window): CellPartsCollection {
return new CellPartsCollection(targetWindow, this.contentParts.concat(other), this.overlayParts);
}
concatOverlayPart(other: readonly CellOverlayPart[]): CellPartsCollection {
return new CellPartsCollection(this.contentParts, this.overlayParts.concat(other));
concatOverlayPart(other: readonly CellOverlayPart[], targetWindow: Window): CellPartsCollection {
return new CellPartsCollection(targetWindow, this.contentParts, this.overlayParts.concat(other));
}
scheduleRenderCell(element: ICellViewModel): void {
@@ -161,7 +162,7 @@ export class CellPartsCollection extends Disposable {
for (const part of this.overlayParts) {
part.renderCell(element);
}
});
}, this.targetWindow);
}
unrenderCell(element: ICellViewModel): void {
@@ -203,7 +204,7 @@ export class CellPartsCollection extends Disposable {
for (const part of this.overlayParts) {
part.updateState(viewCell, e);
}
});
}, this.targetWindow);
}
updateForExecutionState(viewCell: ICellViewModel, e: ICellExecutionStateChangedEvent) {
@@ -215,6 +216,6 @@ export class CellPartsCollection extends Disposable {
for (const part of this.overlayParts) {
part.updateForExecutionState(viewCell, e);
}
});
}, this.targetWindow);
}
}
@@ -58,7 +58,7 @@ export class CodeCell extends Disposable {
const cellEditorOptions = this._register(new CellEditorOptions(this.notebookEditor.getBaseCellEditorOptions(viewCell.language), this.notebookEditor.notebookOptions, this.configurationService));
this._outputContainerRenderer = this.instantiationService.createInstance(CellOutputContainer, notebookEditor, viewCell, templateData, { limit: outputDisplayLimit });
this.cellParts = this._register(templateData.cellParts.concatContentPart([cellEditorOptions, this._outputContainerRenderer]));
this.cellParts = this._register(templateData.cellParts.concatContentPart([cellEditorOptions, this._outputContainerRenderer], DOM.getWindow(notebookEditor.getDomNode())));
// this.viewCell.layoutInfo.editorHeight or estimation when this.viewCell.layoutInfo.editorHeight === 0
const editorHeight = this.calculateInitEditorHeight();
@@ -146,7 +146,7 @@ export class CodeCell extends Disposable {
this._pendingLayout?.dispose();
this._pendingLayout = DOM.modify(() => {
this.cellParts.updateInternalLayoutNow(this.viewCell);
});
}, DOM.getWindow(this.templateData.container));
}
private updateForOutputHover() {
@@ -289,7 +289,7 @@ export class NotebookCellList extends WorkbenchList<CellViewModel> implements ID
if (this._isInLayout) {
DOM.scheduleAtNextAnimationFrame(() => {
updateVisibleRanges();
});
}, DOM.getWindow(container));
}
updateVisibleRanges();
}));
@@ -297,7 +297,7 @@ export class NotebookCellList extends WorkbenchList<CellViewModel> implements ID
if (this._isInLayout) {
DOM.scheduleAtNextAnimationFrame(() => {
updateVisibleRanges();
});
}, DOM.getWindow(container));
}
updateVisibleRanges();
}));
@@ -369,7 +369,7 @@ export class NotebookCellList extends WorkbenchList<CellViewModel> implements ID
}
this._updateElementsInWebview(viewDiffs);
}));
}, DOM.getWindow(this.rowsContainer)));
}
}));
@@ -162,7 +162,7 @@ export class MarkupCellRenderer extends AbstractCellRenderer implements IListRen
this.notebookEditor));
const focusIndicatorBottom = new FastDomNode(DOM.append(container, $('.cell-focus-indicator.cell-focus-indicator-bottom')));
const cellParts = new CellPartsCollection([
const cellParts = new CellPartsCollection(DOM.getWindow(rootContainer), [
templateDisposables.add(scopedInstaService.createInstance(CellEditorStatusBar, this.notebookEditor, container, editorPart, undefined)),
templateDisposables.add(new CellFocusIndicator(this.notebookEditor, titleToolbar, focusIndicatorTop, focusIndicatorLeft, focusIndicatorRight, focusIndicatorBottom)),
templateDisposables.add(new FoldedCellHint(this.notebookEditor, DOM.append(container, $('.notebook-folded-hint')))),
@@ -306,7 +306,7 @@ export class CodeCellRenderer extends AbstractCellRenderer implements IListRende
this.notebookEditor));
const focusIndicatorPart = templateDisposables.add(new CellFocusIndicator(this.notebookEditor, titleToolbar, focusIndicatorTop, focusIndicatorLeft, focusIndicatorRight, focusIndicatorBottom));
const cellParts = new CellPartsCollection([
const cellParts = new CellPartsCollection(DOM.getWindow(rootContainer), [
focusIndicatorPart,
templateDisposables.add(scopedInstaService.createInstance(CellEditorStatusBar, this.notebookEditor, container, editorPart, editor)),
templateDisposables.add(scopedInstaService.createInstance(CellProgressBar, editorPart, cellInputCollapsedContainer)),
@@ -115,7 +115,7 @@ export class NotebookEditorContextKeys {
layoutDisposable.add(DOM.scheduleAtNextAnimationFrame(() => {
recomputeOutputsExistence();
}));
}, DOM.getWindow(this._editor.getDomNode())));
});
};
@@ -24,8 +24,8 @@ class NotebookDiffEditorModel extends EditorModel implements INotebookDiffEditor
export class NotebookDiffEditorInput extends DiffEditorInput {
static create(instantiationService: IInstantiationService, resource: URI, name: string | undefined, description: string | undefined, originalResource: URI, viewType: string) {
const original = NotebookEditorInput.create(instantiationService, originalResource, viewType);
const modified = NotebookEditorInput.create(instantiationService, resource, viewType);
const original = NotebookEditorInput.getOrCreate(instantiationService, originalResource, undefined, viewType);
const modified = NotebookEditorInput.getOrCreate(instantiationService, resource, undefined, viewType);
return instantiationService.createInstance(NotebookDiffEditorInput, name, description, original, modified, viewType);
}
@@ -41,8 +41,24 @@ export interface NotebookEditorInputOptions {
export class NotebookEditorInput extends AbstractResourceEditorInput {
static create(instantiationService: IInstantiationService, resource: URI, viewType: string, options: NotebookEditorInputOptions = {}) {
return instantiationService.createInstance(NotebookEditorInput, resource, viewType, options);
private static EditorCache: Record<string, NotebookEditorInput> = {};
static getOrCreate(instantiationService: IInstantiationService, resource: URI, preferredResource: URI | undefined, viewType: string, options: NotebookEditorInputOptions = {}) {
const cacheId = `${resource.toString()}|${viewType}|${options._workingCopy?.typeId}`;
let editor = NotebookEditorInput.EditorCache[cacheId];
if (!editor) {
editor = instantiationService.createInstance(NotebookEditorInput, resource, preferredResource, viewType, options);
NotebookEditorInput.EditorCache[cacheId] = editor;
editor.onWillDispose(() => {
delete NotebookEditorInput.EditorCache[cacheId];
});
} else if (preferredResource) {
editor.setPreferredResource(preferredResource);
}
return editor;
}
static readonly ID: string = 'workbench.input.notebook';
@@ -53,19 +69,19 @@ export class NotebookEditorInput extends AbstractResourceEditorInput {
constructor(
resource: URI,
preferredResource: URI | undefined,
public readonly viewType: string,
public readonly options: NotebookEditorInputOptions,
@INotebookService private readonly _notebookService: INotebookService,
@INotebookEditorModelResolverService private readonly _notebookModelResolverService: INotebookEditorModelResolverService,
@IFileDialogService private readonly _fileDialogService: IFileDialogService,
@IInstantiationService private readonly _instantiationService: IInstantiationService,
@ILabelService labelService: ILabelService,
@IFileService fileService: IFileService,
@IFilesConfigurationService filesConfigurationService: IFilesConfigurationService,
@IExtensionService extensionService: IExtensionService,
@IEditorService editorService: IEditorService
) {
super(resource, undefined, labelService, fileService, filesConfigurationService);
super(resource, preferredResource, labelService, fileService, filesConfigurationService);
this._defaultDirtyState = !!options.startDirty;
// Automatically resolve this input when the "wanted" model comes to life via
@@ -253,20 +269,12 @@ export class NotebookEditorInput extends AbstractResourceEditorInput {
// called when users rename a notebook document
override async rename(group: GroupIdentifier, target: URI): Promise<IMoveResult | undefined> {
if (this._editorModelReference) {
const contributedNotebookProviders = this._notebookService.getContributedNotebookTypes(target);
return { editor: { resource: target }, options: { override: this.viewType } };
if (contributedNotebookProviders.find(provider => provider.id === this._editorModelReference!.object.viewType)) {
return this._move(group, target);
}
}
return undefined;
}
private _move(_group: GroupIdentifier, newResource: URI): { editor: EditorInput } {
const editorInput = NotebookEditorInput.create(this._instantiationService, newResource, this.viewType);
return { editor: editorInput };
}
override async revert(_group: GroupIdentifier, options?: IRevertOptions): Promise<void> {
if (this._editorModelReference && this._editorModelReference.object.isDirty()) {
await this._editorModelReference.object.revert(options);
@@ -336,7 +344,7 @@ export class NotebookEditorInput extends AbstractResourceEditorInput {
override toUntyped(): IResourceEditorInput {
return {
resource: this.preferredResource,
resource: this.resource,
options: {
override: this.viewType
}
@@ -13,6 +13,7 @@ import { IAccessibilityService } from 'vs/platform/accessibility/common/accessib
import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService';
import { IFileService } from 'vs/platform/files/common/files';
import { IStorageService } from 'vs/platform/storage/common/storage';
import { IUriIdentityService } from 'vs/platform/uriIdentity/common/uriIdentity';
import { NotebookProviderInfoStore } from 'vs/workbench/contrib/notebook/browser/services/notebookServiceImpl';
import { INotebookEditorModelResolverService } from 'vs/workbench/contrib/notebook/common/notebookEditorModelResolverService';
import { NotebookProviderInfo } from 'vs/workbench/contrib/notebook/common/notebookProvider';
@@ -43,7 +44,8 @@ suite('NotebookProviderInfoStore', function () {
new class extends mock<IFileService>() {
override hasProvider() { return true; }
},
new class extends mock<INotebookEditorModelResolverService>() { }
new class extends mock<INotebookEditorModelResolverService>() { },
new class extends mock<IUriIdentityService>() { }
);
disposables.add(store);
@@ -239,28 +239,24 @@
.scm-view .scm-input {
height: 100%;
display: flex;
align-items: center;
padding-left: 11px;
border-radius: 2px;
}
.scm-view .scm-input .actions {
position: absolute;
top: 7px;
right: 20px;
z-index: 2;
.scm-view .scm-input .scm-editor .scm-editor-toolbar {
padding: 1px 3px 1px 1px;
}
.scm-view .scm-input .actions .actions-container {
background-color: var(--vscode-input-background);
.scm-view .scm-input .scm-editor .scm-editor-toolbar.hidden {
display: none;
}
.scm-view .scm-input .actions .action-label {
border-radius: 5px;
outline: 1px dashed var(--vscode-toolbar-hoverOutline);
outline-offset: -1px;
.scm-view .scm-input .scm-editor .scm-editor-toolbar.scroll-decoration {
box-shadow: var(--vscode-scrollbar-shadow) 0 6px 6px -6px inset;
}
.scm-view .scm-input .actions .action-label.codicon.codicon-debug-stop {
.scm-view .scm-input .scm-editor .scm-editor-toolbar .action-label.codicon.codicon-debug-stop {
color: var(--vscode-icon-foreground) !important;
}
@@ -275,10 +271,12 @@
.scm-view .scm-editor {
box-sizing: border-box;
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: flex-start;
box-sizing: border-box;
border: 1px solid var(--vscode-input-border, transparent);
background-color: var(--vscode-input-background);
border-radius: 2px;
}
.scm-view .button-container {
@@ -329,31 +327,23 @@
outline: 1px solid var(--vscode-panelInput-border);
}
.scm-view .scm-editor-container {
position: relative;
box-sizing: border-box;
background-color: var(--vscode-input-background);
border: 1px solid var(--vscode-input-border, transparent);
border-radius: 2px;
}
.scm-view .scm-editor-container.synthetic-focus,
.monaco-workbench .part.panel .scm-view .scm-editor-container.synthetic-focus {
.scm-view .scm-editor.synthetic-focus,
.monaco-workbench .part.panel .scm-view .scm-editor.synthetic-focus {
outline: 1px solid var(--vscode-focusBorder);
outline-offset: -1px;
}
.scm-view .scm-editor-container.validation-info {
.scm-view .scm-editor.validation-info {
outline: 1px solid var(--vscode-inputValidation-infoBorder) !important;
outline-offset: -1px;
}
.scm-view .scm-editor-container.validation-warning {
.scm-view .scm-editor.validation-warning {
outline: 1px solid var(--vscode-inputValidation-warningBorder) !important;
outline-offset: -1px;
}
.scm-view .scm-editor-container.validation-error {
.scm-view .scm-editor.validation-error {
outline: 1px solid var(--vscode-inputValidation-errorBorder) !important;
outline-offset: -1px;
}
@@ -267,6 +267,11 @@ Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Configuration).regis
markdownDescription: localize('inputFontSize', "Controls the font size for the input message in pixels."),
default: 13
},
'scm.inputMaxLines': {
type: 'number',
markdownDescription: localize('inputMaxLines', "Controls the maximum number of lines that the input will auto-grow to."),
default: 10
},
'scm.alwaysShowRepositories': {
type: 'boolean',
markdownDescription: localize('alwaysShowRepository', "Controls whether repositories should always be visible in the Source Control view."),
@@ -96,6 +96,7 @@ import { fillEditorsDragData } from 'vs/workbench/browser/dnd';
import { ElementsDragAndDropData } from 'vs/base/browser/ui/list/listView';
import { CodeDataTransfers } from 'vs/platform/dnd/browser/dnd';
import { FormatOnType } from 'vs/editor/contrib/format/browser/formatActions';
import { EditorOption } from 'vs/editor/common/config/editorOptions';
type TreeElement = ISCMRepository | ISCMInput | ISCMActionButton | ISCMResourceGroup | IResourceNode<ISCMResource, ISCMResourceGroup> | ISCMResource;
@@ -1808,6 +1809,7 @@ class SCMInputWidget {
private editorContainer: HTMLElement;
private placeholderTextContainer: HTMLElement;
private inputEditor: CodeEditorWidget;
private toolbarContainer: HTMLElement;
private actionBar: ActionBar;
private readonly disposables = new DisposableStore();
@@ -1837,7 +1839,7 @@ class SCMInputWidget {
}
this.clearValidation();
this.editorContainer.classList.remove('synthetic-focus');
this.element.classList.remove('synthetic-focus');
this.repositoryDisposables.clear();
this.repositoryIdContextKey.set(input?.repository.id);
@@ -1958,11 +1960,8 @@ class SCMInputWidget {
this.repositoryDisposables.add(input.onDidChangeEnablement(enabled => updateEnablement(enabled)));
updateEnablement(input.enabled);
// ActionBar
// Toolbar
const onDidChangeActionButton = () => {
// Update placeholder width to accommodate for the action bar
this.placeholderTextContainer.style.width = input.actionButton ? 'calc(100% - 26px)' : '100%';
this.actionBar.clear();
if (!input.actionButton) {
return;
@@ -1976,6 +1975,7 @@ class SCMInputWidget {
() => this.commandService.executeCommand(input.actionButton!.command.id, ...(input.actionButton!.command.arguments || [])));
this.actionBar.push(action, { icon: true, label: false });
this.layout();
};
this.repositoryDisposables.add(input.onDidChangeActionButton(onDidChangeActionButton, this));
@@ -2027,6 +2027,7 @@ class SCMInputWidget {
this.element = append(container, $('.scm-editor'));
this.editorContainer = append(this.element, $('.scm-editor-container'));
this.placeholderTextContainer = append(this.editorContainer, $('.scm-editor-placeholder'));
this.toolbarContainer = append(this.element, $('.scm-editor-toolbar'));
const fontFamily = this.getInputEditorFontFamily();
const fontSize = this.getInputEditorFontSize();
@@ -2049,7 +2050,10 @@ class SCMInputWidget {
wrappingIndent: 'none',
padding: { top: 2, bottom: 2 },
quickSuggestions: false,
scrollbar: { alwaysConsumeMouseWheel: false },
scrollbar: {
alwaysConsumeMouseWheel: false,
vertical: 'hidden'
},
overflowWidgetsDomNode,
formatOnType: true,
renderWhitespace: 'none',
@@ -2076,9 +2080,6 @@ class SCMInputWidget {
])
};
this.actionBar = new ActionBar(append(this.element, $('.actions')));
this.disposables.add(this.actionBar);
const services = new ServiceCollection([IContextKeyService, contextKeyService2]);
const instantiationService2 = instantiationService.createChild(services);
this.inputEditor = instantiationService2.createInstance(CodeEditorWidget, this.editorContainer, editorOptions, codeEditorWidgetOptions);
@@ -2089,11 +2090,11 @@ class SCMInputWidget {
this.scmViewService.focus(this.input.repository);
}
this.editorContainer.classList.add('synthetic-focus');
this.element.classList.add('synthetic-focus');
this.renderValidation();
}));
this.disposables.add(this.inputEditor.onDidBlurEditorText(() => {
this.editorContainer.classList.remove('synthetic-focus');
this.element.classList.remove('synthetic-focus');
setTimeout(() => {
if (!this.validation || !this.validationHasFocus) {
@@ -2113,6 +2114,9 @@ class SCMInputWidget {
firstLineKey.set(viewPosition.lineNumber === 1 && viewPosition.column === 1);
lastLineKey.set(viewPosition.lineNumber === lastLineNumber && viewPosition.column === lastLineCol);
}));
this.disposables.add(this.inputEditor.onDidScrollChange(e => {
this.toolbarContainer.classList.toggle('scroll-decoration', e.scrollTop > 0);
}));
const relevantSettings = [
'scm.inputFontFamily',
@@ -2153,16 +2157,23 @@ class SCMInputWidget {
}));
this.onDidChangeContentHeight = Event.signal(Event.filter(this.inputEditor.onDidContentSizeChange, e => e.contentHeightChanged, this.disposables));
// Toolbar
this.actionBar = new ActionBar(this.toolbarContainer);
this.disposables.add(this.actionBar);
}
getContentHeight(): number {
const editorContentHeight = this.inputEditor.getContentHeight();
return Math.min(editorContentHeight, 134);
const editorContextHeightMax = this.getInputEditorMaxHeight();
return Math.min(editorContentHeight, editorContextHeightMax);
}
layout(): void {
const editorHeight = this.getContentHeight();
const dimension = new Dimension(this.element.clientWidth - 2, editorHeight);
const toolbarWidth = this.toolbarContainer.clientWidth;
const dimension = new Dimension(this.element.clientWidth - toolbarWidth, editorHeight);
if (dimension.width < 0) {
this.lastLayoutWasTrash = true;
@@ -2171,6 +2182,8 @@ class SCMInputWidget {
this.lastLayoutWasTrash = false;
this.inputEditor.layout(dimension);
this.placeholderTextContainer.style.width = `${dimension.width}px`;
this.toolbarContainer.classList.toggle('hidden', this.input?.actionButton === undefined);
this.renderValidation();
if (this.shouldFocusAfterLayout) {
@@ -2187,7 +2200,7 @@ class SCMInputWidget {
}
this.inputEditor.focus();
this.editorContainer.classList.add('synthetic-focus');
this.element.classList.add('synthetic-focus');
}
hasFocus(): boolean {
@@ -2197,9 +2210,9 @@ class SCMInputWidget {
private renderValidation(): void {
this.clearValidation();
this.editorContainer.classList.toggle('validation-info', this.validation?.type === InputValidationType.Information);
this.editorContainer.classList.toggle('validation-warning', this.validation?.type === InputValidationType.Warning);
this.editorContainer.classList.toggle('validation-error', this.validation?.type === InputValidationType.Error);
this.element.classList.toggle('validation-info', this.validation?.type === InputValidationType.Information);
this.element.classList.toggle('validation-warning', this.validation?.type === InputValidationType.Warning);
this.element.classList.toggle('validation-error', this.validation?.type === InputValidationType.Error);
if (!this.validation || !this.inputEditor.hasTextFocus()) {
return;
@@ -2208,16 +2221,16 @@ class SCMInputWidget {
const disposables = new DisposableStore();
this.validationDisposable = this.contextViewService.showContextView({
getAnchor: () => this.editorContainer,
getAnchor: () => this.element,
render: container => {
this.editorContainer.style.borderBottomLeftRadius = '0';
this.editorContainer.style.borderBottomRightRadius = '0';
this.element.style.borderBottomLeftRadius = '0';
this.element.style.borderBottomRightRadius = '0';
const validationContainer = append(container, $('.scm-editor-validation-container'));
validationContainer.classList.toggle('validation-info', this.validation!.type === InputValidationType.Information);
validationContainer.classList.toggle('validation-warning', this.validation!.type === InputValidationType.Warning);
validationContainer.classList.toggle('validation-error', this.validation!.type === InputValidationType.Error);
validationContainer.style.width = `${this.editorContainer.clientWidth + 2}px`;
validationContainer.style.width = `${this.element.clientWidth + 2}px`;
const element = append(validationContainer, $('.scm-editor-validation'));
const message = this.validation!.message;
@@ -2229,8 +2242,8 @@ class SCMInputWidget {
disposables.add(tracker.onDidFocus(() => (this.validationHasFocus = true)));
disposables.add(tracker.onDidBlur(() => {
this.validationHasFocus = false;
this.editorContainer.style.borderBottomLeftRadius = '2px';
this.editorContainer.style.borderBottomRightRadius = '2px';
this.element.style.borderBottomLeftRadius = '2px';
this.element.style.borderBottomRightRadius = '2px';
this.contextViewService.hideContextView();
}));
@@ -2239,8 +2252,8 @@ class SCMInputWidget {
actionHandler: {
callback: (link) => {
openLinkFromMarkdown(this.openerService, link, message.isTrusted);
this.editorContainer.style.borderBottomLeftRadius = '2px';
this.editorContainer.style.borderBottomRightRadius = '2px';
this.element.style.borderBottomLeftRadius = '2px';
this.element.style.borderBottomRightRadius = '2px';
this.contextViewService.hideContextView();
},
disposables: disposables
@@ -2253,8 +2266,8 @@ class SCMInputWidget {
const actionbar = new ActionBar(actionsContainer);
const action = new Action('scmInputWidget.validationMessage.close', localize('label.close', "Close"), ThemeIcon.asClassName(Codicon.close), true, () => {
this.contextViewService.hideContextView();
this.editorContainer.style.borderBottomLeftRadius = '2px';
this.editorContainer.style.borderBottomRightRadius = '2px';
this.element.style.borderBottomLeftRadius = '2px';
this.element.style.borderBottomRightRadius = '2px';
});
disposables.add(actionbar);
actionbar.push(action, { icon: true, label: false });
@@ -2263,8 +2276,8 @@ class SCMInputWidget {
},
onHide: () => {
this.validationHasFocus = false;
this.editorContainer.style.borderBottomLeftRadius = '2px';
this.editorContainer.style.borderBottomRightRadius = '2px';
this.element.style.borderBottomLeftRadius = '2px';
this.element.style.borderBottomRightRadius = '2px';
disposables.dispose();
},
anchorAlignment: AnchorAlignment.LEFT
@@ -2289,6 +2302,19 @@ class SCMInputWidget {
return this.configurationService.getValue<number>('scm.inputFontSize');
}
private getInputEditorMaxLines(): number {
return this.configurationService.getValue<number>('scm.inputMaxLines');
}
private getInputEditorMaxHeight(): number {
const maxLines = this.getInputEditorMaxLines();
const fontSize = this.getInputEditorFontSize();
const lineHeight = this.computeLineHeight(fontSize);
const { top, bottom } = this.inputEditor.getOption(EditorOption.padding);
return maxLines * lineHeight + top + bottom;
}
private computeLineHeight(fontSize: number): number {
return Math.round(fontSize * 1.5);
}
@@ -6,7 +6,7 @@
import 'vs/css!./media/scm';
import { localize } from 'vs/nls';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { VIEWLET_ID } from 'vs/workbench/contrib/scm/common/scm';
import { ISCMViewService, VIEWLET_ID } from 'vs/workbench/contrib/scm/common/scm';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
import { IThemeService } from 'vs/platform/theme/common/themeService';
@@ -21,6 +21,7 @@ import { ViewPaneContainer } from 'vs/workbench/browser/parts/views/viewPaneCont
export class SCMViewPaneContainer extends ViewPaneContainer {
constructor(
@ISCMViewService private readonly scmViewService: ISCMViewService,
@IWorkbenchLayoutService layoutService: IWorkbenchLayoutService,
@ITelemetryService telemetryService: ITelemetryService,
@IInstantiationService instantiationService: IInstantiationService,
@@ -47,4 +48,9 @@ export class SCMViewPaneContainer extends ViewPaneContainer {
override getTitle(): string {
return localize('source control', "Source Control");
}
override getActionsContext(): unknown {
return this.scmViewService.visibleRepositories.length === 1 ? this.scmViewService.visibleRepositories[0].provider : undefined;
}
}
@@ -29,7 +29,7 @@ import { ACTIVE_GROUP, IEditorService, SIDE_GROUP } from 'vs/workbench/services/
import { ITextQueryBuilderOptions, QueryBuilder } from 'vs/workbench/services/search/common/queryBuilder';
import { IPatternInfo, ITextQuery, VIEW_ID } from 'vs/workbench/services/search/common/search';
export const TEXT_SEARCH_QUICK_ACCESS_PREFIX = '% ';
export const TEXT_SEARCH_QUICK_ACCESS_PREFIX = '%';
const DEFAULT_TEXT_QUERY_BUILDER_OPTIONS: ITextQueryBuilderOptions = {
_reason: 'quickAccessSearch',
@@ -83,6 +83,9 @@ export class TextSearchQuickAccess extends PickerQuickAccessProvider<IPickerQuic
override provide(picker: IQuickPick<IPickerQuickAccessItem>, token: CancellationToken, runOptions?: IQuickAccessProviderRunOptions): IDisposable {
const disposables = new DisposableStore();
if (TEXT_SEARCH_QUICK_ACCESS_PREFIX.length < picker.value.length) {
picker.valueSelection = [TEXT_SEARCH_QUICK_ACCESS_PREFIX.length, picker.value.length];
}
disposables.add(super.provide(picker, token, runOptions));
disposables.add(picker.onDidHide(() => this.searchModel.searchResult.toggleHighlights(false)));
disposables.add(picker.onDidAccept(() => this.searchModel.searchResult.toggleHighlights(false)));
@@ -272,7 +275,9 @@ export class TextSearchQuickAccess extends PickerQuickAccessProvider<IPickerQuic
return {
picks: syncResult,
additionalPicks: allMatches.asyncResults
.then(asyncResults => this._getPicksFromMatches(asyncResults, MAX_FILES_SHOWN - matches.length))
.then(asyncResults => (asyncResults.length + syncResult.length === 0) ? [{
label: localize('noAnythingResults', "No matching results")
}] : this._getPicksFromMatches(asyncResults, MAX_FILES_SHOWN - matches.length))
.then(picks => {
if (picks.length > 0) {
this.searchModel.searchResult.toggleHighlights(true);
@@ -41,7 +41,7 @@ import { CellSearchModel, ICellMatch, contentMatchesToTextSearchMatches, isIFile
import { INotebookSearchService } from 'vs/workbench/contrib/search/common/notebookSearch';
import { ReplacePattern } from 'vs/workbench/services/search/common/replace';
import { IFileMatch, IPatternInfo, ISearchComplete, ISearchConfigurationProperties, ISearchProgressItem, ISearchRange, ISearchService, ITextQuery, ITextSearchContext, ITextSearchMatch, ITextSearchPreviewOptions, ITextSearchResult, ITextSearchStats, OneLineRange, resultIsMatch, SearchCompletionExitCode, SearchSortOrder } from 'vs/workbench/services/search/common/search';
import { addContextToEditorMatches, editorMatchesToTextSearchResults } from 'vs/workbench/services/search/common/searchHelpers';
import { getTextSearchMatchWithModelContext, editorMatchesToTextSearchResults } from 'vs/workbench/services/search/common/searchHelpers';
export class Match {
@@ -245,7 +245,7 @@ export class CellMatch {
return;
}
this.cell.resolveTextModel().then((textModel) => {
const textResultsWithContext = addContextToEditorMatches(textSearchMatches, textModel, this.parent.parent().query!);
const textResultsWithContext = getTextSearchMatchWithModelContext(textSearchMatches, textModel, this.parent.parent().query!);
const contexts = textResultsWithContext.filter((result => !resultIsMatch(result)) as ((a: any) => a is ITextSearchContext));
contexts.map(context => ({ ...context, lineNumber: context.lineNumber + 1 }))
.forEach((context) => { this._context.set(context.lineNumber, context.text); });
@@ -567,10 +567,7 @@ export class FileMatch extends Disposable implements IFileMatch {
});
});
this.addContext(
addContextToEditorMatches(textSearchResults, model, this.parent().parent().query!)
.filter((result => !resultIsMatch(result)) as ((a: any) => a is ITextSearchContext))
.map(context => ({ ...context, lineNumber: context.lineNumber + 1 })));
this.addContext(getTextSearchMatchWithModelContext(textSearchResults, model, this.parent().parent().query!));
this._onChange.fire({ forceUpdateModel: modelChange });
this.updateHighlights();
@@ -1041,7 +1038,7 @@ export class FolderMatch extends Disposable {
}
public createIntermediateFolderMatch(resource: URI, id: string, index: number, query: ITextQuery, baseWorkspaceFolder: FolderMatchWorkspaceRoot): FolderMatchWithResource {
const folderMatch = this.instantiationService.createInstance(FolderMatchWithResource, resource, id, index, query, this, this._searchResult, baseWorkspaceFolder);
const folderMatch = this._register(this.instantiationService.createInstance(FolderMatchWithResource, resource, id, index, query, this, this._searchResult, baseWorkspaceFolder));
this.configureIntermediateMatch(folderMatch);
this.doAddFolder(folderMatch);
return folderMatch;
@@ -1049,7 +1046,7 @@ export class FolderMatch extends Disposable {
public configureIntermediateMatch(folderMatch: FolderMatchWithResource) {
const disposable = folderMatch.onChange((event) => this.onFolderChange(folderMatch, event));
folderMatch.onDispose(() => disposable.dispose());
this._register(folderMatch.onDispose(() => disposable.dispose()));
}
clear(clearingAll = false): void {
@@ -1176,7 +1173,9 @@ export class FolderMatch extends Disposable {
updated.push(existingFileMatch);
existingFileMatch.addContext(rawFileMatch.results);
if (rawFileMatch.results && rawFileMatch.results.length > 0) {
existingFileMatch.addContext(rawFileMatch.results);
}
} else {
if (this instanceof FolderMatchWorkspaceRoot || this instanceof FolderMatchNoRoot) {
const fileMatch = this.createAndConfigureFileMatch(rawFileMatch, searchInstanceID);
@@ -1379,7 +1378,7 @@ export class FolderMatchWorkspaceRoot extends FolderMatchWithResource {
);
parent.doAddFile(fileMatch);
const disposable = fileMatch.onChange(({ didRemove }) => parent.onFileChange(fileMatch, didRemove));
fileMatch.onDispose(() => disposable.dispose());
this._register(fileMatch.onDispose(() => disposable.dispose()));
return fileMatch;
}
@@ -1431,17 +1430,17 @@ export class FolderMatchNoRoot extends FolderMatch {
}
createAndConfigureFileMatch(rawFileMatch: IFileMatch, searchInstanceID: string): FileMatch {
const fileMatch = this.instantiationService.createInstance(
const fileMatch = this._register(this.instantiationService.createInstance(
FileMatch,
this._query.contentPattern,
this._query.previewOptions,
this._query.maxResults,
this, rawFileMatch,
null,
searchInstanceID);
searchInstanceID));
this.doAddFile(fileMatch);
const disposable = fileMatch.onChange(({ didRemove }) => this.onFileChange(fileMatch, didRemove));
fileMatch.onDispose(() => disposable.dispose());
this._register(fileMatch.onDispose(() => disposable.dispose()));
return fileMatch;
}
}
@@ -1590,7 +1589,7 @@ export class SearchResult extends Disposable {
private _showHighlights: boolean = false;
private _query: ITextQuery | null = null;
private _rangeHighlightDecorations: RangeHighlightDecorations;
private disposePastResults: () => void = () => { };
private disposePastResults: () => Promise<void> = () => Promise.resolve();
private _isDirty = false;
private _onWillChangeModelListener: IDisposable | undefined;
private _onDidChangeModelListener: IDisposable | undefined;
@@ -1674,10 +1673,11 @@ export class SearchResult extends Disposable {
set query(query: ITextQuery | null) {
// When updating the query we could change the roots, so keep a reference to them to clean up when we trigger `disposePastResults`
const oldFolderMatches = this.folderMatches();
new Promise<void>(resolve => this.disposePastResults = resolve)
.then(() => oldFolderMatches.forEach(match => match.clear()))
.then(() => oldFolderMatches.forEach(match => match.dispose()))
.then(() => this._isDirty = false);
this.disposePastResults = async () => {
oldFolderMatches.forEach(match => match.clear());
oldFolderMatches.forEach(match => match.dispose());
this._isDirty = false;
};
this._rangeHighlightDecorations.removeHighlightRange();
this._folderMatchesMap = TernarySearchTree.forUris<FolderMatchWithResource>(key => this.uriIdentityService.extUri.ignorePathCasing(key));
@@ -1736,12 +1736,12 @@ export class SearchResult extends Disposable {
private _createBaseFolderMatch(resource: URI | null, id: string, index: number, query: ITextQuery): FolderMatch {
let folderMatch: FolderMatch;
if (resource) {
folderMatch = this.instantiationService.createInstance(FolderMatchWorkspaceRoot, resource, id, index, query, this);
folderMatch = this._register(this.instantiationService.createInstance(FolderMatchWorkspaceRoot, resource, id, index, query, this));
} else {
folderMatch = this.instantiationService.createInstance(FolderMatchNoRoot, id, index, query, this);
folderMatch = this._register(this.instantiationService.createInstance(FolderMatchNoRoot, id, index, query, this));
}
const disposable = folderMatch.onChange((event) => this._onChange.fire(event));
folderMatch.onDispose(() => disposable.dispose());
this._register(folderMatch.onDispose(() => disposable.dispose()));
return folderMatch;
}
@@ -1922,13 +1922,13 @@ export class SearchResult extends Disposable {
this._rangeHighlightDecorations.removeHighlightRange();
}
override dispose(): void {
override async dispose(): Promise<void> {
this._onWillChangeModelListener?.dispose();
this._onDidChangeModelListener?.dispose();
this.disposePastResults();
this.disposeMatches();
this._rangeHighlightDecorations.dispose();
this.disposeMatches();
super.dispose();
await this.disposePastResults();
}
}
@@ -2080,7 +2080,7 @@ export class SearchModel extends Disposable {
this._searchResult.query = this._searchQuery;
const progressEmitter = new Emitter<void>();
const progressEmitter = this._register(new Emitter<void>());
this._replacePattern = new ReplacePattern(this.replaceString, this._searchQuery.contentPattern);
// In search on type case, delay the streaming of results just a bit, so that we don't flash the only "local results" fast path
@@ -2099,14 +2099,21 @@ export class SearchModel extends Disposable {
}
const start = Date.now();
let event: IDisposable | undefined;
Promise.race([asyncResults, Event.toPromise(progressEmitter.event)]).finally(() => {
const progressEmitterPromise = new Promise(resolve => {
event = Event.once(progressEmitter.event)(resolve);
return event;
});
Promise.race([asyncResults, progressEmitterPromise]).finally(() => {
/* __GDPR__
"searchResultsFirstRender" : {
"owner": "roblourens",
"duration" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth", "isMeasurement": true }
}
*/
event?.dispose();
this.telemetryService.publicLog('searchResultsFirstRender', { duration: Date.now() - start });
});
@@ -2331,9 +2338,9 @@ export class RangeHighlightDecorations implements IDisposable {
dispose() {
if (this._model) {
this.removeHighlightRange();
this._modelDisposables.dispose();
this._model = null;
}
this._modelDisposables.dispose();
}
private static readonly _RANGE_HIGHLIGHT_DECORATION = ModelDecorationOptions.register({
@@ -1281,13 +1281,6 @@ export class SearchView extends ViewPane {
}
editor = editor ?? this.editorService.activeTextEditorControl;
if (isDiffEditor(editor)) {
if (editor.getOriginalEditor().hasTextFocus()) {
editor = editor.getOriginalEditor();
} else {
editor = editor.getModifiedEditor();
}
}
if (!editor) {
return null;
@@ -2147,7 +2140,17 @@ export function getEditorSelectionFromMatch(element: FileMatchOrMatch, viewModel
return undefined;
}
export function getSelectionTextFromEditor(allowUnselectedWord: boolean, editor: IEditor): string | null {
export function getSelectionTextFromEditor(allowUnselectedWord: boolean, activeEditor: IEditor): string | null {
let editor = activeEditor;
if (isDiffEditor(editor)) {
if (editor.getOriginalEditor().hasTextFocus()) {
editor = editor.getOriginalEditor();
} else {
editor = editor.getModifiedEditor();
}
}
if (!isCodeEditor(editor) || !editor.hasModel()) {
return null;
@@ -18,16 +18,18 @@ import { MockObjectTree } from 'vs/workbench/contrib/search/test/browser/mockSea
import { ILabelService } from 'vs/platform/label/common/label';
import { INotebookEditorService } from 'vs/workbench/contrib/notebook/browser/services/notebookEditorService';
import { createFileUriFromPathFromRoot, stubModelService, stubNotebookEditorService } from 'vs/workbench/contrib/search/test/browser/searchTestCommon';
import { ensureNoDisposablesAreLeakedInTestSuite } from 'vs/base/test/common/utils';
suite('Search Actions', () => {
let instantiationService: TestInstantiationService;
let counter: number;
const store = ensureNoDisposablesAreLeakedInTestSuite();
setup(() => {
instantiationService = new TestInstantiationService();
instantiationService.stub(IModelService, stubModelService(instantiationService));
instantiationService.stub(INotebookEditorService, stubNotebookEditorService(instantiationService));
instantiationService.stub(IModelService, stubModelService(instantiationService, (e) => store.add(e)));
instantiationService.stub(INotebookEditorService, stubNotebookEditorService(instantiationService, (e) => store.add(e)));
instantiationService.stub(IKeybindingService, {});
instantiationService.stub(ILabelService, { getUriBasenameLabel: (uri: URI) => '' });
instantiationService.stub(IKeybindingService, 'resolveKeybinding', (keybinding: Keybinding) => USLayoutResolvedKeybinding.resolveKeybinding(keybinding, OS));
@@ -113,14 +115,18 @@ suite('Search Actions', () => {
};
const searchModel = instantiationService.createInstance(SearchModel);
store.add(searchModel);
const folderMatch = instantiationService.createInstance(FolderMatch, URI.file('somepath'), '', 0, {
type: QueryType.Text, folderQueries: [{ folder: createFileUriFromPathFromRoot() }], contentPattern: {
pattern: ''
}
}, searchModel.searchResult, searchModel.searchResult, null);
return instantiationService.createInstance(FileMatch, {
store.add(folderMatch);
const fileMatch = instantiationService.createInstance(FileMatch, {
pattern: ''
}, undefined, undefined, folderMatch, rawMatch, null, '');
store.add(fileMatch);
return fileMatch;
}
function aMatch(fileMatch: FileMatch): Match {
@@ -40,6 +40,7 @@ import { INotebookSearchService } from 'vs/workbench/contrib/search/common/noteb
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { MockContextKeyService } from 'vs/platform/keybinding/test/common/mockKeybindingService';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { ensureNoDisposablesAreLeakedInTestSuite } from 'vs/base/test/common/utils';
const nullEvent = new class {
id: number = -1;
@@ -65,6 +66,7 @@ const lineOneRange = new OneLineRange(1, 0, 1);
suite('SearchModel', () => {
let instantiationService: TestInstantiationService;
const store = ensureNoDisposablesAreLeakedInTestSuite();
const testSearchStats: IFileSearchStats = {
fromCache: false,
@@ -92,7 +94,11 @@ suite('SearchModel', () => {
instantiationService.stub(INotebookEditorService, stubNotebookEditorService(instantiationService));
instantiationService.stub(ISearchService, {});
instantiationService.stub(ISearchService, 'textSearch', Promise.resolve({ results: [] }));
instantiationService.stub(IUriIdentityService, new UriIdentityService(new FileService(new NullLogService())));
const fileService = new FileService(new NullLogService());
store.add(fileService);
const uriIdentityService = new UriIdentityService(fileService);
store.add(uriIdentityService);
instantiationService.stub(IUriIdentityService, uriIdentityService);
instantiationService.stub(ILogService, new NullLogService());
});
@@ -164,12 +170,18 @@ suite('SearchModel', () => {
function canceleableSearchService(tokenSource: CancellationTokenSource): ISearchService {
return <ISearchService>{
textSearch(query: ITextQuery, token?: CancellationToken, onProgress?: (result: ISearchProgressItem) => void): Promise<ISearchComplete> {
token?.onCancellationRequested(() => tokenSource.cancel());
const disposable = token?.onCancellationRequested(() => tokenSource.cancel());
if (disposable) {
store.add(disposable);
}
return this.textSearchSplitSyncAsync(query, token, onProgress).asyncResults;
},
fileSearch(query: IFileQuery, token?: CancellationToken): Promise<ISearchComplete> {
token?.onCancellationRequested(() => tokenSource.cancel());
const disposable = token?.onCancellationRequested(() => tokenSource.cancel());
if (disposable) {
store.add(disposable);
}
return new Promise(resolve => {
queueMicrotask(() => {
resolve(<any>{});
@@ -177,7 +189,10 @@ suite('SearchModel', () => {
});
},
textSearchSplitSyncAsync(query: ITextQuery, token?: CancellationToken | undefined, onProgress?: ((result: ISearchProgressItem) => void) | undefined): { syncResults: ISearchComplete; asyncResults: Promise<ISearchComplete> } {
token?.onCancellationRequested(() => tokenSource.cancel());
const disposable = token?.onCancellationRequested(() => tokenSource.cancel());
if (disposable) {
store.add(disposable);
}
return {
syncResults: {
results: [],
@@ -219,7 +234,10 @@ suite('SearchModel', () => {
completeData: Promise<ISearchComplete>;
allScannedFiles: Promise<ResourceSet>;
} {
token?.onCancellationRequested(() => tokenSource?.cancel());
const disposable = token?.onCancellationRequested(() => tokenSource?.cancel());
if (disposable) {
store.add(disposable);
}
const localResults = new ResourceMap<IFileMatchWithCells | null>(uri => uri.path);
results.forEach(r => {
@@ -252,6 +270,7 @@ suite('SearchModel', () => {
instantiationService.stub(INotebookSearchService, notebookSearchServiceWithInfo([], undefined));
const testObject: SearchModel = instantiationService.createInstance(SearchModel);
store.add(testObject);
await testObject.search({ contentPattern: { pattern: 'somestring' }, type: QueryType.Text, folderQueries }).asyncResults;
const actual = testObject.searchResult.matches();
@@ -352,6 +371,7 @@ suite('SearchModel', () => {
const notebookSearchService = instantiationService.stub(INotebookSearchService, notebookSearchServiceWithInfo([aRawMatchWithCells('/1', cellMatchMd, cellMatchCode)], undefined));
const notebookSearch = sinon.spy(notebookSearchService, "notebookSearch");
const model: SearchModel = instantiationService.createInstance(SearchModel);
store.add(model);
await model.search({ contentPattern: { pattern: 'test' }, type: QueryType.Text, folderQueries }).asyncResults;
const actual = model.searchResult.matches();
@@ -404,6 +424,7 @@ suite('SearchModel', () => {
instantiationService.stub(INotebookSearchService, notebookSearchServiceWithInfo([], undefined));
const testObject: SearchModel = instantiationService.createInstance(SearchModel);
store.add(testObject);
await testObject.search({ contentPattern: { pattern: 'somestring' }, type: QueryType.Text, folderQueries }).asyncResults;
assert.ok(target.calledThrice);
@@ -421,6 +442,7 @@ suite('SearchModel', () => {
instantiationService.stub(INotebookSearchService, notebookSearchServiceWithInfo([], undefined));
const testObject = instantiationService.createInstance(SearchModel);
store.add(testObject);
const result = testObject.search({ contentPattern: { pattern: 'somestring' }, type: QueryType.Text, folderQueries }).asyncResults;
return result.then(() => {
@@ -443,6 +465,7 @@ suite('SearchModel', () => {
instantiationService.stub(INotebookSearchService, notebookSearchServiceWithInfo([], undefined));
const testObject = instantiationService.createInstance(SearchModel);
store.add(testObject);
const result = testObject.search({ contentPattern: { pattern: 'somestring' }, type: QueryType.Text, folderQueries }).asyncResults;
return result.then(() => {
@@ -466,6 +489,7 @@ suite('SearchModel', () => {
instantiationService.stub(INotebookSearchService, notebookSearchServiceWithInfo([], undefined));
const testObject = instantiationService.createInstance(SearchModel);
store.add(testObject);
const result = testObject.search({ contentPattern: { pattern: 'somestring' }, type: QueryType.Text, folderQueries }).asyncResults;
return result.then(() => { }, () => {
@@ -488,6 +512,7 @@ suite('SearchModel', () => {
instantiationService.stub(INotebookSearchService, notebookSearchServiceWithInfo([], undefined));
const testObject = instantiationService.createInstance(SearchModel);
store.add(testObject);
const result = testObject.search({ contentPattern: { pattern: 'somestring' }, type: QueryType.Text, folderQueries }).asyncResults;
deferredPromise.cancel();
@@ -511,6 +536,7 @@ suite('SearchModel', () => {
instantiationService.stub(ISearchService, searchServiceWithResults(results, { limitHit: false, messages: [], results: [] }));
instantiationService.stub(INotebookSearchService, notebookSearchServiceWithInfo([], undefined));
const testObject: SearchModel = instantiationService.createInstance(SearchModel);
store.add(testObject);
await testObject.search({ contentPattern: { pattern: 'somestring' }, type: QueryType.Text, folderQueries }).asyncResults;
assert.ok(!testObject.searchResult.isEmpty());
@@ -522,9 +548,11 @@ suite('SearchModel', () => {
test('Search Model: Previous search is cancelled when new search is called', async () => {
const tokenSource = new CancellationTokenSource();
store.add(tokenSource);
instantiationService.stub(ISearchService, canceleableSearchService(tokenSource));
instantiationService.stub(INotebookSearchService, notebookSearchServiceWithInfo([], tokenSource));
const testObject: SearchModel = instantiationService.createInstance(SearchModel);
store.add(testObject);
testObject.search({ contentPattern: { pattern: 'somestring' }, type: QueryType.Text, folderQueries });
instantiationService.stub(ISearchService, searchServiceWithResults([]));
instantiationService.stub(INotebookSearchService, notebookSearchServiceWithInfo([], undefined));
@@ -542,6 +570,7 @@ suite('SearchModel', () => {
instantiationService.stub(INotebookSearchService, notebookSearchServiceWithInfo([], undefined));
const testObject: SearchModel = instantiationService.createInstance(SearchModel);
store.add(testObject);
await testObject.search({ contentPattern: { pattern: 're' }, type: QueryType.Text, folderQueries }).asyncResults;
testObject.replaceString = 'hello';
let match = testObject.searchResult.matches()[0].matches()[0];
@@ -578,14 +607,18 @@ suite('SearchModel', () => {
const config = new TestConfigurationService();
config.setUserConfiguration('search', { searchOnType: true });
instantiationService.stub(IConfigurationService, config);
return instantiationService.createInstance(ModelService);
const modelService = instantiationService.createInstance(ModelService);
store.add(modelService);
return modelService;
}
function stubNotebookEditorService(instantiationService: TestInstantiationService): INotebookEditorService {
instantiationService.stub(IEditorGroupsService, new TestEditorGroupsService());
instantiationService.stub(IContextKeyService, new MockContextKeyService());
instantiationService.stub(IEditorService, new TestEditorService());
return instantiationService.createInstance(NotebookEditorWidgetService);
const notebookEditorWidgetService = instantiationService.createInstance(NotebookEditorWidgetService);
store.add(notebookEditorWidgetService);
return notebookEditorWidgetService;
}
});
@@ -17,6 +17,7 @@ import { TestInstantiationService } from 'vs/platform/instantiation/test/common/
import { createFileUriFromPathFromRoot, stubModelService, stubNotebookEditorService } from 'vs/workbench/contrib/search/test/browser/searchTestCommon';
import { IModelService } from 'vs/editor/common/services/model';
import { INotebookEditorService } from 'vs/workbench/contrib/notebook/browser/services/notebookEditorService';
import { ensureNoDisposablesAreLeakedInTestSuite } from 'vs/base/test/common/utils';
suite('searchNotebookHelpers', () => {
let instantiationService: TestInstantiationService;
@@ -28,12 +29,16 @@ suite('searchNotebookHelpers', () => {
let markdownContentResults: ITextSearchMatch[];
let codeContentResults: ITextSearchMatch[];
let codeWebviewResults: ITextSearchMatch[];
const store = ensureNoDisposablesAreLeakedInTestSuite();
let counter: number = 0;
setup(() => {
instantiationService = new TestInstantiationService();
instantiationService.stub(IModelService, stubModelService(instantiationService));
instantiationService.stub(INotebookEditorService, stubNotebookEditorService(instantiationService));
store.add(instantiationService);
const modelService = stubModelService(instantiationService, (e) => store.add(e));
const notebookEditorService = stubNotebookEditorService(instantiationService, (e) => store.add(e));
instantiationService.stub(IModelService, modelService);
instantiationService.stub(INotebookEditorService, notebookEditorService);
mdInputCell = {
cellKind: CellKind.Markup, textBuffer: <IReadonlyTextBuffer>{
getLineContent(lineNumber: number): string {
@@ -201,14 +206,19 @@ suite('searchNotebookHelpers', () => {
};
const searchModel = instantiationService.createInstance(SearchModel);
store.add(searchModel);
const folderMatch = instantiationService.createInstance(FolderMatch, URI.file('somepath'), '', 0, {
type: QueryType.Text, folderQueries: [{ folder: createFileUriFromPathFromRoot() }], contentPattern: {
pattern: ''
}
}, searchModel.searchResult, searchModel.searchResult, null);
return instantiationService.createInstance(FileMatch, {
const fileMatch = instantiationService.createInstance(FileMatch, {
pattern: ''
}, undefined, undefined, folderMatch, rawMatch, null, '');
store.add(folderMatch);
store.add(fileMatch);
return fileMatch;
}
});
});
@@ -35,19 +35,25 @@ import { addToSearchResult, createFileUriFromPathFromRoot, getRootName } from 'v
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { MockContextKeyService } from 'vs/platform/keybinding/test/common/mockKeybindingService';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { ensureNoDisposablesAreLeakedInTestSuite } from 'vs/base/test/common/utils';
const lineOneRange = new OneLineRange(1, 0, 1);
suite('SearchResult', () => {
let instantiationService: TestInstantiationService;
const store = ensureNoDisposablesAreLeakedInTestSuite();
setup(() => {
instantiationService = new TestInstantiationService();
instantiationService.stub(ITelemetryService, NullTelemetryService);
instantiationService.stub(IModelService, stubModelService(instantiationService));
instantiationService.stub(INotebookEditorService, stubNotebookEditorService(instantiationService));
instantiationService.stub(IUriIdentityService, new UriIdentityService(new FileService(new NullLogService())));
const fileService = new FileService(new NullLogService());
store.add(fileService);
const uriIdentityService = new UriIdentityService(fileService);
store.add(uriIdentityService);
instantiationService.stub(IUriIdentityService, uriIdentityService);
instantiationService.stubPromise(IReplaceService, {});
instantiationService.stub(IReplaceService, 'replace', () => Promise.resolve(null));
instantiationService.stub(ILabelService, new MockLabelService());
@@ -164,7 +170,9 @@ suite('SearchResult', () => {
test('Match -> FileMatch -> SearchResult hierarchy exists', function () {
const searchModel = instantiationService.createInstance(SearchModel);
store.add(searchModel);
const searchResult = instantiationService.createInstance(SearchResult, searchModel);
store.add(searchResult);
const fileMatch = aFileMatch('far/boo', searchResult);
const lineMatch = new Match(fileMatch, ['foo bar'], new OneLineRange(0, 0, 3), new OneLineRange(1, 0, 3));
@@ -283,8 +291,8 @@ suite('SearchResult', () => {
aRawMatch('/2',
new TextSearchMatch('preview 2', lineOneRange))]);
testObject.matches()[0].onDispose(target1);
testObject.matches()[1].onDispose(target2);
store.add(testObject.matches()[0].onDispose(target1));
store.add(testObject.matches()[1].onDispose(target2));
testObject.dispose();
@@ -300,7 +308,7 @@ suite('SearchResult', () => {
aRawMatch('/1',
new TextSearchMatch('preview 1', lineOneRange))]);
const objectToRemove = testObject.matches()[0];
testObject.onChange(target);
store.add(testObject.onChange(target));
testObject.remove(objectToRemove);
@@ -317,7 +325,7 @@ suite('SearchResult', () => {
aRawMatch('/2',
new TextSearchMatch('preview 2', lineOneRange))]);
const arrayToRemove = testObject.matches();
testObject.onChange(target);
store.add(testObject.onChange(target));
testObject.remove(arrayToRemove);
@@ -362,7 +370,8 @@ suite('SearchResult', () => {
addToSearchResult(testObject, [
aRawMatch('/1',
new TextSearchMatch('preview 1', lineOneRange))]);
testObject.onChange(target);
store.add(testObject.onChange(target));
const objectToRemove = testObject.matches()[0];
testObject.replace(objectToRemove);
@@ -399,7 +408,7 @@ suite('SearchResult', () => {
const arrayToRemove = [folderMatch, fileMatch, match];
const expectedArrayResult = folderMatch.allDownstreamFileMatches().concat([fileMatch, match.parent()]);
testObject.onChange(target);
store.add(testObject.onChange(target));
testObject.batchRemove(arrayToRemove);
assert.ok(target.calledOnce);
@@ -428,7 +437,7 @@ suite('SearchResult', () => {
const arrayToRemove = [folderMatch, fileMatch, match];
testObject.onChange(target);
store.add(testObject.onChange(target));
await testObject.batchReplace(arrayToRemove);
assert.ok(target.calledOnce);
@@ -491,7 +500,7 @@ suite('SearchResult', () => {
const expectedArrayResult = folderMatch.allDownstreamFileMatches();
testObject.onChange(target);
store.add(testObject.onChange(target));
testObject.remove(folderMatch);
assert.ok(target.calledOnce);
assert.deepStrictEqual([{ elements: expectedArrayResult, removed: true, added: false, clearingAll: false }], target.args[0]);
@@ -505,7 +514,7 @@ suite('SearchResult', () => {
const expectedArrayResult = folderMatch.allDownstreamFileMatches();
testObject.onChange(target);
store.add(testObject.onChange(target));
await testObject.batchReplace([folderMatch]);
assert.deepStrictEqual([{ elements: expectedArrayResult, removed: true, added: false }], target.args[0]);
@@ -520,13 +529,17 @@ suite('SearchResult', () => {
results: lineMatches
};
const root = searchResult?.folderMatches()[0];
return instantiationService.createInstance(FileMatch, {
const fileMatch = instantiationService.createInstance(FileMatch, {
pattern: ''
}, undefined, undefined, root, rawMatch, null, '');
store.add(fileMatch);
return fileMatch;
}
function aSearchResult(): SearchResult {
const searchModel = instantiationService.createInstance(SearchModel);
store.add(searchModel);
searchModel.searchResult.query = {
type: QueryType.Text, folderQueries: [{ folder: createFileUriFromPathFromRoot() }], contentPattern: {
pattern: ''
@@ -551,14 +564,18 @@ suite('SearchResult', () => {
const config = new TestConfigurationService();
config.setUserConfiguration('search', { searchOnType: true });
instantiationService.stub(IConfigurationService, config);
return instantiationService.createInstance(ModelService);
const modelService = instantiationService.createInstance(ModelService);
store.add(modelService);
return modelService;
}
function stubNotebookEditorService(instantiationService: TestInstantiationService): INotebookEditorService {
instantiationService.stub(IEditorGroupsService, new TestEditorGroupsService());
instantiationService.stub(IContextKeyService, new MockContextKeyService());
instantiationService.stub(IEditorService, new TestEditorService());
return instantiationService.createInstance(NotebookEditorWidgetService);
const notebookEditorWidgetService = instantiationService.createInstance(NotebookEditorWidgetService);
store.add(notebookEditorWidgetService);
return notebookEditorWidgetService;
}
function getPopulatedSearchResult() {
@@ -3,6 +3,7 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { IDisposable } from 'vs/base/common/lifecycle';
import { isWindows } from 'vs/base/common/platform';
import { URI } from 'vs/base/common/uri';
import { IModelService } from 'vs/editor/common/services/model';
@@ -43,19 +44,23 @@ export function getRootName(): string {
}
}
export function stubModelService(instantiationService: TestInstantiationService): IModelService {
export function stubModelService(instantiationService: TestInstantiationService, addDisposable: (e: IDisposable) => void): IModelService {
instantiationService.stub(IThemeService, new TestThemeService());
const config = new TestConfigurationService();
config.setUserConfiguration('search', { searchOnType: true });
instantiationService.stub(IConfigurationService, config);
return instantiationService.createInstance(ModelService);
const modelService = instantiationService.createInstance(ModelService);
addDisposable(modelService);
return modelService;
}
export function stubNotebookEditorService(instantiationService: TestInstantiationService): INotebookEditorService {
export function stubNotebookEditorService(instantiationService: TestInstantiationService, addDisposable: (e: IDisposable) => void): INotebookEditorService {
instantiationService.stub(IEditorGroupsService, new TestEditorGroupsService());
instantiationService.stub(IContextKeyService, new MockContextKeyService());
instantiationService.stub(IEditorService, new TestEditorService());
return instantiationService.createInstance(NotebookEditorWidgetService);
const notebookEditorWidgetService = instantiationService.createInstance(NotebookEditorWidgetService);
addDisposable(notebookEditorWidgetService);
return notebookEditorWidgetService;
}
export function addToSearchResult(searchResult: SearchResult, allRaw: IFileMatch[], searchInstanceID = '') {
@@ -6,16 +6,11 @@ import * as assert from 'assert';
import { URI } from 'vs/base/common/uri';
import { ILanguageConfigurationService } from 'vs/editor/common/languages/languageConfigurationRegistry';
import { IModelService } from 'vs/editor/common/services/model';
import { ModelService } from 'vs/editor/common/services/modelService';
import { TestLanguageConfigurationService } from 'vs/editor/test/common/modes/testLanguageConfigurationService';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService';
import { FileService } from 'vs/platform/files/common/fileService';
import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock';
import { ILabelService } from 'vs/platform/label/common/label';
import { ILogService, NullLogService } from 'vs/platform/log/common/log';
import { IThemeService } from 'vs/platform/theme/common/themeService';
import { TestThemeService } from 'vs/platform/theme/test/common/testThemeService';
import { IUriIdentityService } from 'vs/platform/uriIdentity/common/uriIdentity';
import { UriIdentityService } from 'vs/platform/uriIdentity/common/uriIdentityService';
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
@@ -25,25 +20,25 @@ import { MockLabelService } from 'vs/workbench/services/label/test/common/mockLa
import { IFileMatch, ITextSearchMatch, OneLineRange, QueryType, SearchSortOrder } from 'vs/workbench/services/search/common/search';
import { TestContextService } from 'vs/workbench/test/common/workbenchTestServices';
import { INotebookEditorService } from 'vs/workbench/contrib/notebook/browser/services/notebookEditorService';
import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
import { TestEditorGroupsService, TestEditorService } from 'vs/workbench/test/browser/workbenchTestServices';
import { NotebookEditorWidgetService } from 'vs/workbench/contrib/notebook/browser/services/notebookEditorServiceImpl';
import { createFileUriFromPathFromRoot, getRootName } from 'vs/workbench/contrib/search/test/browser/searchTestCommon';
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { MockContextKeyService } from 'vs/platform/keybinding/test/common/mockKeybindingService';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { createFileUriFromPathFromRoot, getRootName, stubModelService, stubNotebookEditorService } from 'vs/workbench/contrib/search/test/browser/searchTestCommon';
import { ensureNoDisposablesAreLeakedInTestSuite } from 'vs/base/test/common/utils';
suite('Search - Viewlet', () => {
let instantiation: TestInstantiationService;
const store = ensureNoDisposablesAreLeakedInTestSuite();
setup(() => {
instantiation = new TestInstantiationService();
instantiation.stub(ILanguageConfigurationService, TestLanguageConfigurationService);
instantiation.stub(IModelService, stubModelService(instantiation));
instantiation.stub(INotebookEditorService, stubNotebookEditorService(instantiation));
instantiation.stub(IModelService, stubModelService(instantiation, (e) => store.add(e)));
instantiation.stub(INotebookEditorService, stubNotebookEditorService(instantiation, (e) => store.add(e)));
instantiation.set(IWorkspaceContextService, new TestContextService(TestWorkspace));
instantiation.stub(IUriIdentityService, new UriIdentityService(new FileService(new NullLogService())));
const fileService = new FileService(new NullLogService());
store.add(fileService);
const uriIdentityService = new UriIdentityService(fileService);
store.add(uriIdentityService);
instantiation.stub(IUriIdentityService, uriIdentityService);
instantiation.stub(ILabelService, new MockLabelService());
instantiation.stub(ILogService, new NullLogService());
});
@@ -182,22 +177,29 @@ suite('Search - Viewlet', () => {
resource: URI.file('/' + path),
results: lineMatches
};
return instantiation.createInstance(FileMatch, {
const fileMatch = instantiation.createInstance(FileMatch, {
pattern: ''
}, undefined, undefined, parentFolder ?? aFolderMatch('', 0), rawMatch, null, '');
store.add(fileMatch);
return fileMatch;
}
function aFolderMatch(path: string, index: number, parent?: SearchResult): FolderMatch {
const searchModel = instantiation.createInstance(SearchModel);
return instantiation.createInstance(FolderMatch, createFileUriFromPathFromRoot(path), path, index, {
store.add(searchModel);
const folderMatch = instantiation.createInstance(FolderMatch, createFileUriFromPathFromRoot(path), path, index, {
type: QueryType.Text, folderQueries: [{ folder: createFileUriFromPathFromRoot() }], contentPattern: {
pattern: ''
}
}, parent ?? aSearchResult().folderMatches()[0], searchModel.searchResult, null);
store.add(folderMatch);
return folderMatch;
}
function aSearchResult(): SearchResult {
const searchModel = instantiation.createInstance(SearchModel);
store.add(searchModel);
searchModel.searchResult.query = {
type: QueryType.Text, folderQueries: [{ folder: createFileUriFromPathFromRoot() }], contentPattern: {
pattern: ''
@@ -205,21 +207,4 @@ suite('Search - Viewlet', () => {
};
return searchModel.searchResult;
}
function stubModelService(instantiationService: TestInstantiationService): IModelService {
instantiationService.stub(IThemeService, new TestThemeService());
const config = new TestConfigurationService();
config.setUserConfiguration('search', { searchOnType: true });
instantiationService.stub(IConfigurationService, config);
return instantiationService.createInstance(ModelService);
}
function stubNotebookEditorService(instantiationService: TestInstantiationService): INotebookEditorService {
instantiationService.stub(IEditorGroupsService, new TestEditorGroupsService());
instantiationService.stub(IContextKeyService, new MockContextKeyService());
instantiationService.stub(IEditorService, new TestEditorService());
return instantiationService.createInstance(NotebookEditorWidgetService);
}
});
@@ -53,7 +53,6 @@ export class TerminalViewPane extends ViewPane {
private _parentDomElement: HTMLElement | undefined;
private _terminalTabbedView?: TerminalTabbedView;
get terminalTabbedView(): TerminalTabbedView | undefined { return this._terminalTabbedView; }
private _isWelcomeShowing: boolean = false;
private _isInitialized: boolean = false;
private _newDropdown: DropdownWithPrimaryActionViewItem | undefined;
private readonly _dropdownMenu: IMenu;
@@ -87,13 +86,18 @@ export class TerminalViewPane extends ViewPane {
}));
this._register(this._terminalService.onDidChangeInstances(() => {
if (!this._isWelcomeShowing) {
return;
// If the first terminal is opened, hide the welcome view
// and if the last one is closed, show it again
if (this._hasWelcomeScreen() && this._terminalService.instances.length <= 1) {
this._onDidChangeViewWelcomeState.fire();
}
this._isWelcomeShowing = true;
this._onDidChangeViewWelcomeState.fire();
if (!this._terminalTabbedView && this._parentDomElement) {
if (!this._parentDomElement) { return; }
// If we do not have the tab view yet, create it now.
if (!this._terminalTabbedView) {
this._createTabsView();
}
// If we just opened our first terminal, layout
if (this._terminalService.instances.length === 1) {
this.layoutBody(this._parentDomElement.offsetHeight, this._parentDomElement.offsetWidth);
}
}));
@@ -200,7 +204,7 @@ export class TerminalViewPane extends ViewPane {
this._register(this.onDidChangeBodyVisibility(async visible => {
this._viewShowing.set(visible);
if (visible) {
if (!this._terminalService.isProcessSupportRegistered) {
if (this._hasWelcomeScreen()) {
this._onDidChangeViewWelcomeState.fire();
}
this._initializeTerminal(false);
@@ -319,9 +323,12 @@ export class TerminalViewPane extends ViewPane {
}
}
private _hasWelcomeScreen(): boolean {
return !this._terminalService.isProcessSupportRegistered;
}
override shouldShowWelcome(): boolean {
this._isWelcomeShowing = !this._terminalService.isProcessSupportRegistered && this._terminalService.instances.length === 0;
return this._isWelcomeShowing;
return this._hasWelcomeScreen() && this._terminalService.instances.length === 0;
}
}

Some files were not shown because too many files have changed in this diff Show More