diff --git a/.editorconfig b/.editorconfig
index 40de22df5..7ffdc78df 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -1,6 +1,7 @@
root = true
[*]
+charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
diff --git a/.gitattributes b/.gitattributes
index bf0e54a56..6aa281e5b 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -3,6 +3,8 @@
###############################################################################
* -text
+*.inc linguist-language=cpp
+
###############################################################################
# Set default behavior for command prompt diff.
#
diff --git a/.github/actions/spelling/allow/allow.txt b/.github/actions/spelling/allow/allow.txt
index e4abdb7d8..35742a611 100644
--- a/.github/actions/spelling/allow/allow.txt
+++ b/.github/actions/spelling/allow/allow.txt
@@ -1,6 +1,7 @@
apc
calt
ccmp
+changelog
cybersecurity
Apc
clickable
@@ -41,6 +42,7 @@ Lorigin
maxed
mkmk
mru
+noreply
nje
ogonek
ok'd
diff --git a/.github/actions/spelling/allow/apis.txt b/.github/actions/spelling/allow/apis.txt
index 4b6fbe4f5..19f5fb487 100644
--- a/.github/actions/spelling/allow/apis.txt
+++ b/.github/actions/spelling/allow/apis.txt
@@ -25,6 +25,7 @@ DERR
dlldata
DONTADDTORECENT
DWORDLONG
+enumset
environstrings
EXPCMDFLAGS
EXPCMDSTATE
diff --git a/.github/actions/spelling/allow/microsoft.txt b/.github/actions/spelling/allow/microsoft.txt
index 87d7a3d8c..a96139e3c 100644
--- a/.github/actions/spelling/allow/microsoft.txt
+++ b/.github/actions/spelling/allow/microsoft.txt
@@ -24,7 +24,9 @@ DTDs
DWINRT
enablewttlogging
Intelli
+IVisual
LKG
+LOCKFILE
Lxss
mfcribbon
microsoft
diff --git a/.github/actions/spelling/allow/names.txt b/.github/actions/spelling/allow/names.txt
index 27ba53635..3635d3723 100644
--- a/.github/actions/spelling/allow/names.txt
+++ b/.github/actions/spelling/allow/names.txt
@@ -53,6 +53,7 @@ oldnewthing
opengl
osgwiki
pabhojwa
+panos
paulcam
pauldotknopf
PGP
diff --git a/.github/actions/spelling/expect/expect.txt b/.github/actions/spelling/expect/expect.txt
index efd6edff8..c12609802 100644
--- a/.github/actions/spelling/expect/expect.txt
+++ b/.github/actions/spelling/expect/expect.txt
@@ -194,6 +194,8 @@ cascadia
cassert
castsi
catid
+carlos
+zamora
cazamor
CBash
cbegin
@@ -2690,6 +2692,7 @@ WINDOWPOSCHANGING
windowproc
windowrect
windowsapp
+windowsdeveloper
windowsinternalstring
WINDOWSIZE
windowsx
diff --git a/.github/actions/spelling/patterns/patterns.txt b/.github/actions/spelling/patterns/patterns.txt
index 882243396..47f902f90 100644
--- a/.github/actions/spelling/patterns/patterns.txt
+++ b/.github/actions/spelling/patterns/patterns.txt
@@ -24,3 +24,4 @@ VERIFY_ARE_EQUAL\(L"[^"]+"
std::memory_order_[\w]+
D2DERR_SHADER_COMPILE_FAILED
TIL_FEATURE_[0-9A-Z_]+
+vcvars\w*
diff --git a/doc/building.md b/doc/building.md
index b00d7c45f..5a5b46ff0 100644
--- a/doc/building.md
+++ b/doc/building.md
@@ -15,7 +15,7 @@ Import-Module .\tools\OpenConsole.psm1
Set-MsBuildDevEnvironment
Get-Format
```
-After, go to Tools > Options > Text Editor > C++ > Formatting and checking "Use custom clang-format.exe file" in Visual Studio and choose the clang-format.exe in the repository at /packages/clang-format.win-x86.10.0.0/tools/clang-format.exe by clicking "browse" right under the check box.
+After, go to Tools > Options > Text Editor > C++ > Formatting and check "Use custom clang-format.exe file" in Visual Studio and choose the clang-format.exe in the repository at /packages/clang-format.win-x86.10.0.0/tools/clang-format.exe by clicking "browse" right under the check box.
### Building in PowerShell
diff --git a/doc/cascadia/profiles.schema.json b/doc/cascadia/profiles.schema.json
index 319e0bae7..4f55d576b 100644
--- a/doc/cascadia/profiles.schema.json
+++ b/doc/cascadia/profiles.schema.json
@@ -1,8 +1,8 @@
{
"$id": "https://github.com/microsoft/terminal/blob/main/doc/cascadia/profiles.schema.json",
- "$schema": "https://json-schema.org/draft/2020-12/schema#",
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "Microsoft's Windows Terminal Settings Profile Schema",
- "definitions": {
+ "$defs": {
"KeyChordSegment": {
"pattern": "^(?:(?:ctrl|alt|shift|win)\\+)*(?:app|backspace|browser_(?:back|forward|refresh|stop|search|favorites|home)|comma|delete|down|end|enter|esc|escape|home|insert|left|menu|minus|pagedown|pageup|period|pgdn|pgup|plus|right|space|tab|up|f(?:1\\d?|2[0-4]?|[3-9])|numpad\\d|numpad_(?:\\d|add|decimal|divide|minus|multiply|period|plus|subtract)|(?:vk|sc)\\((?:[1-9]|1?\\d{2}|2[0-4]\\d|25[0-5])\\)|[^\\s+])(?:\\+(?:ctrl|alt|shift|win))*$",
"type": "string",
@@ -61,28 +61,42 @@
"type": "string"
},
"foreground": {
- "$ref": "#/definitions/Color",
+ "$ref": "#/$defs/Color",
"default": "#cccccc",
"description": "Sets the text color when unfocused. Overrides \"foreground\" from the color scheme. Uses hex color format: \"#rrggbb\".",
- "type": ["string", "null"]
+ "type": [
+ "string",
+ "null"
+ ]
},
"background": {
- "$ref": "#/definitions/Color",
+ "$ref": "#/$defs/Color",
"default": "#0c0c0c",
"description": "Sets the background color of the text when unfocused. Overrides \"background\" from the color scheme. Uses hex color format: \"#rrggbb\".",
- "type": ["string", "null"]
+ "type": [
+ "string",
+ "null"
+ ]
},
"selectionBackground": {
"oneOf": [
- {"$ref": "#/definitions/Color"},
- { "type": "null" }
+ {
+ "$ref": "#/$defs/Color"
+ },
+ {
+ "type": "null"
+ }
],
"description": "Sets the background color of selected text when unfocused. Overrides selectionBackground set in the color scheme. Uses hex color format: \"#rrggbb\"."
},
"cursorColor": {
"oneOf": [
- { "$ref": "#/definitions/Color" },
- {"type": "null"}
+ {
+ "$ref": "#/$defs/Color"
+ },
+ {
+ "type": "null"
+ }
],
"description": "Sets the color of the cursor when unfocused. Overrides the cursor color from the color scheme. Uses hex color format: \"#rrggbb\"."
},
@@ -103,14 +117,20 @@
"description": "Sets the percentage height of the cursor (when unfocused) starting from the bottom. Only works when cursorShape is set to \"vintage\". Accepts values from 1-100.",
"maximum": 100,
"minimum": 1,
- "type": ["integer","null"],
+ "type": [
+ "integer",
+ "null"
+ ],
"default": 25
},
"backgroundImage": {
"description": "Sets the file location of the image to draw over the window background when unfocused.",
"oneOf": [
{
- "type": ["string", null]
+ "type": [
+ "string",
+ "null"
+ ]
},
{
"enum": [
@@ -118,7 +138,10 @@
]
}
],
- "type": [ "string", "null" ]
+ "type": [
+ "string",
+ "null"
+ ]
},
"backgroundImageOpacity": {
"default": 1.0,
@@ -220,7 +243,9 @@
"description": "Sets the DWrite font features for the given font. For example, { \"ss01\": 1, \"liga\":0 } will enable ss01 and disable ligatures.",
"type": "object",
"patternProperties": {
- "^(([A-Za-z0-9]){4})$": { "type": "integer" }
+ "^(([A-Za-z0-9]){4})$": {
+ "type": "integer"
+ }
},
"additionalProperties": false
},
@@ -228,7 +253,9 @@
"description": "Sets the DWrite font axes for the given font. For example, { \"wght\": 200 } will set the font weight to 200.",
"type": "object",
"patternProperties": {
- "^([A-Za-z]{4})$": { "type": "number" }
+ "^([A-Za-z]{4})$": {
+ "type": "number"
+ }
},
"additionalProperties": false
}
@@ -319,7 +346,9 @@
"previous",
"nextInOrder",
"previousInOrder",
- "first"
+ "first",
+ "parent",
+ "child"
],
"type": "string"
},
@@ -420,7 +449,7 @@
"description": "The index of the profile in the new tab dropdown (starting at 0)"
},
"tabColor": {
- "$ref": "#/definitions/Color",
+ "$ref": "#/$defs/Color",
"default": null,
"description": "If provided, will set the tab's color to the given value"
},
@@ -436,9 +465,11 @@
},
"type": "object"
},
- "SwitchToAdjacentTabArgs" : {
+ "SwitchToAdjacentTabArgs": {
"oneOf": [
- { "type": "null" },
+ {
+ "type": "null"
+ },
{
"enum": [
"mru",
@@ -453,7 +484,7 @@
"properties": {
"action": {
"description": "The action to execute",
- "$ref": "#/definitions/ShortcutActionName"
+ "$ref": "#/$defs/ShortcutActionName"
}
},
"required": [
@@ -464,10 +495,15 @@
"AdjustFontSizeAction": {
"description": "Arguments corresponding to an Adjust Font Size Action",
"allOf": [
- { "$ref": "#/definitions/ShortcutAction" },
+ {
+ "$ref": "#/$defs/ShortcutAction"
+ },
{
"properties": {
- "action": { "type": "string", "pattern": "adjustFontSize" },
+ "action": {
+ "type": "string",
+ "pattern": "adjustFontSize"
+ },
"delta": {
"type": "integer",
"default": 0,
@@ -476,15 +512,22 @@
}
}
],
- "required": [ "delta" ]
+ "required": [
+ "delta"
+ ]
},
"CopyAction": {
"description": "Arguments corresponding to a Copy Text Action",
"allOf": [
- { "$ref": "#/definitions/ShortcutAction" },
+ {
+ "$ref": "#/$defs/ShortcutAction"
+ },
{
"properties": {
- "action": { "type": "string", "pattern": "copy" },
+ "action": {
+ "type": "string",
+ "pattern": "copy"
+ },
"singleLine": {
"type": "boolean",
"default": false,
@@ -495,7 +538,7 @@
"description": "When set to `true`, the color and font formatting of selected text is also copied to your clipboard. When set to `false`, only plain text is copied to your clipboard. An array of specific formats can also be used. Supported array values include `html` and `rtf`. Plain text is always copied. Not setting this value inherits the behavior of the `copyFormatting` global setting.",
"oneOf": [
{
- "$ref": "#/definitions/CopyFormat"
+ "$ref": "#/$defs/CopyFormat"
},
{
"type": "null"
@@ -509,11 +552,18 @@
"NewTabAction": {
"description": "Arguments corresponding to a New Tab Action",
"allOf": [
- { "$ref": "#/definitions/ShortcutAction" },
- { "$ref": "#/definitions/NewTerminalArgs" },
+ {
+ "$ref": "#/$defs/ShortcutAction"
+ },
+ {
+ "$ref": "#/$defs/NewTerminalArgs"
+ },
{
"properties": {
- "action": { "type":"string", "pattern": "newTab" }
+ "action": {
+ "type": "string",
+ "pattern": "newTab"
+ }
}
}
]
@@ -521,27 +571,39 @@
"SwitchToTabAction": {
"description": "Arguments corresponding to a Switch To Tab Action",
"allOf": [
- { "$ref": "#/definitions/ShortcutAction" },
+ {
+ "$ref": "#/$defs/ShortcutAction"
+ },
{
"properties": {
- "action": { "type": "string", "pattern": "switchToTab" },
+ "action": {
+ "type": "string",
+ "pattern": "switchToTab"
+ },
"index": {
"type": "integer",
"default": 0,
"description": "Which tab to switch to, with the first being 0"
+ }
}
}
- }
- ],
- "required": [ "index" ]
- },
- "MovePaneAction": {
+ ],
+ "required": [
+ "index"
+ ]
+ },
+ "MovePaneAction": {
"description": "Arguments corresponding to a Move Pane Action",
"allOf": [
- { "$ref": "#/definitions/ShortcutAction" },
+ {
+ "$ref": "#/$defs/ShortcutAction"
+ },
{
"properties": {
- "action": { "type": "string", "pattern": "movePane" },
+ "action": {
+ "type": "string",
+ "pattern": "movePane"
+ },
"index": {
"type": "integer",
"default": 0,
@@ -550,68 +612,94 @@
}
}
],
- "required": [ "index" ]
+ "required": [
+ "index"
+ ]
},
"MoveFocusAction": {
"description": "Arguments corresponding to a Move Focus Action",
"allOf": [
- { "$ref": "#/definitions/ShortcutAction" },
+ {
+ "$ref": "#/$defs/ShortcutAction"
+ },
{
"properties": {
- "action": { "type": "string", "pattern": "moveFocus" },
+ "action": {
+ "type": "string",
+ "pattern": "moveFocus"
+ },
"direction": {
- "$ref": "#/definitions/FocusDirection",
+ "$ref": "#/$defs/FocusDirection",
"default": "left",
- "description": "The direction to move focus in, between panes. Direction can be 'previous' to move to the most recently used pane, or 'nextInOrder' or 'previousInOrder' to move to the next or previous pane."
+ "description": "The direction to move focus in, between panes. Direction can be 'previous' to move to the most recently used pane, 'nextInOrder' or 'previousInOrder' to move to the next or previous pane, 'first' to focus the first pane, or 'parent' or 'child' to move up and down the tree."
}
}
}
],
- "required": [ "direction" ]
+ "required": [
+ "direction"
+ ]
},
"SwapPaneAction": {
"description": "Arguments corresponding to a Swap Pane Action",
"allOf": [
- { "$ref": "#/definitions/ShortcutAction" },
+ {
+ "$ref": "#/$defs/ShortcutAction"
+ },
{
"properties": {
- "action": { "type": "string", "pattern": "swapPane" },
+ "action": {
+ "type": "string",
+ "pattern": "swapPane"
+ },
"direction": {
- "$ref": "#/definitions/FocusDirection",
+ "$ref": "#/$defs/FocusDirection",
"default": "left",
- "description": "The direction to move the focus pane in, swapping panes. Direction can be 'previous' to swap with the most recently used pane, or 'nextInOrder' or 'previousInOrder' to move to the next or previous pane."
+ "description": "The direction to move the focus pane in, swapping panes. Direction can be 'previous' to swap with the most recently used pane, 'nextInOrder' or 'previousInOrder' to move to the next or previous pane, or 'first' to swap with the first pane."
}
}
}
],
- "required": [ "direction" ]
+ "required": [
+ "direction"
+ ]
},
"ResizePaneAction": {
"description": "Arguments corresponding to a Resize Pane Action",
"allOf": [
- { "$ref": "#/definitions/ShortcutAction" },
+ {
+ "$ref": "#/$defs/ShortcutAction"
+ },
{
"properties": {
- "action": { "type": "string", "pattern": "resizePane" },
+ "action": {
+ "type": "string",
+ "pattern": "resizePane"
+ },
"direction": {
- "$ref": "#/definitions/ResizeDirection",
+ "$ref": "#/$defs/ResizeDirection",
"default": "left",
"description": "The direction to move the pane separator in."
}
}
}
],
- "required": [ "direction" ]
+ "required": [
+ "direction"
+ ]
},
"SendInputAction": {
"description": "Arguments corresponding to a Send Input Action",
"allOf": [
{
- "$ref": "#/definitions/ShortcutAction"
+ "$ref": "#/$defs/ShortcutAction"
},
{
"properties": {
- "action": { "type": "string", "pattern": "sendInput" },
+ "action": {
+ "type": "string",
+ "pattern": "sendInput"
+ },
"input": {
"type": "string",
"default": "",
@@ -620,18 +708,27 @@
}
}
],
- "required": [ "input" ]
+ "required": [
+ "input"
+ ]
},
"SplitPaneAction": {
"description": "Arguments corresponding to a Split Pane Action",
"allOf": [
- { "$ref": "#/definitions/ShortcutAction" },
- { "$ref": "#/definitions/NewTerminalArgs" },
+ {
+ "$ref": "#/$defs/ShortcutAction"
+ },
+ {
+ "$ref": "#/$defs/NewTerminalArgs"
+ },
{
"properties": {
- "action": { "type": "string", "pattern": "splitPane" },
+ "action": {
+ "type": "string",
+ "pattern": "splitPane"
+ },
"split": {
- "$ref": "#/definitions/SplitDirection",
+ "$ref": "#/$defs/SplitDirection",
"default": "auto",
"description": "The orientation to split the pane in. Possible values:\n -\"auto\" (splits pane based on remaining space)\n -\"up\" (think [-] and above)\n -\"down\" (think [-] and below)\n -\"left\" (think [|] and to the left)\n -\"right\"(think [|] and to the right)"
},
@@ -654,11 +751,14 @@
"description": "Arguments corresponding to a Open Settings Action",
"allOf": [
{
- "$ref": "#/definitions/ShortcutAction"
+ "$ref": "#/$defs/ShortcutAction"
},
{
"properties": {
- "action": { "type": "string", "pattern": "openSettings" },
+ "action": {
+ "type": "string",
+ "pattern": "openSettings"
+ },
"target": {
"type": "string",
"default": "settingsUI",
@@ -668,7 +768,6 @@
"defaultsFile",
"allFiles",
"settingsUI"
-
]
}
}
@@ -678,12 +777,17 @@
"SetTabColorAction": {
"description": "Arguments corresponding to a Set Tab Color Action",
"allOf": [
- { "$ref": "#/definitions/ShortcutAction" },
+ {
+ "$ref": "#/$defs/ShortcutAction"
+ },
{
"properties": {
- "action": { "type": "string", "pattern": "setTabColor" },
+ "action": {
+ "type": "string",
+ "pattern": "setTabColor"
+ },
"color": {
- "$ref": "#/definitions/Color",
+ "$ref": "#/$defs/Color",
"default": null,
"description": "If provided, will set the tab's color to the given value. If omitted, will reset the tab's color."
}
@@ -694,10 +798,15 @@
"SetColorSchemeAction": {
"description": "Arguments corresponding to a Set Color Scheme Action",
"allOf": [
- { "$ref": "#/definitions/ShortcutAction" },
+ {
+ "$ref": "#/$defs/ShortcutAction"
+ },
{
"properties": {
- "action": { "type": "string", "pattern": "setColorScheme" },
+ "action": {
+ "type": "string",
+ "pattern": "setColorScheme"
+ },
"colorScheme": {
"type": "string",
"default": "",
@@ -706,15 +815,22 @@
}
}
],
- "required": [ "colorScheme" ]
+ "required": [
+ "colorScheme"
+ ]
},
"WtAction": {
"description": "Arguments corresponding to a wt Action",
"allOf": [
- { "$ref": "#/definitions/ShortcutAction" },
+ {
+ "$ref": "#/$defs/ShortcutAction"
+ },
{
"properties": {
- "action": { "type": "string", "pattern": "wt" },
+ "action": {
+ "type": "string",
+ "pattern": "wt"
+ },
"commandline": {
"type": "string",
"default": "",
@@ -723,19 +839,30 @@
}
}
],
- "required": [ "commandline" ]
+ "required": [
+ "commandline"
+ ]
},
"CloseOtherTabsAction": {
"description": "Arguments for a closeOtherTabs action",
"allOf": [
- { "$ref": "#/definitions/ShortcutAction" },
+ {
+ "$ref": "#/$defs/ShortcutAction"
+ },
{
"properties": {
- "action": { "type": "string", "pattern": "closeOtherTabs" },
+ "action": {
+ "type": "string",
+ "pattern": "closeOtherTabs"
+ },
"index": {
"oneOf": [
- { "type": "integer" },
- { "type": "null" }
+ {
+ "type": "integer"
+ },
+ {
+ "type": "null"
+ }
],
"default": null,
"description": "Close the tabs other than the one at this index. If no index is provided, use the focused tab's index."
@@ -747,14 +874,23 @@
"CloseTabsAfterAction": {
"description": "Arguments for a closeTabsAfter action",
"allOf": [
- { "$ref": "#/definitions/ShortcutAction" },
+ {
+ "$ref": "#/$defs/ShortcutAction"
+ },
{
"properties": {
- "action": { "type": "string", "pattern": "closeTabsAfter" },
+ "action": {
+ "type": "string",
+ "pattern": "closeTabsAfter"
+ },
"index": {
"oneOf": [
- { "type": "integer" },
- { "type": "null" }
+ {
+ "type": "integer"
+ },
+ {
+ "type": "null"
+ }
],
"default": null,
"description": "Close the tabs following the tab at this index. If no index is provided, use the focused tab's index."
@@ -766,14 +902,23 @@
"CloseTabAction": {
"description": "Arguments for a closeTab action",
"allOf": [
- { "$ref": "#/definitions/ShortcutAction" },
+ {
+ "$ref": "#/$defs/ShortcutAction"
+ },
{
"properties": {
- "action": { "type": "string", "pattern": "closeTab" },
+ "action": {
+ "type": "string",
+ "pattern": "closeTab"
+ },
"index": {
"oneOf": [
- { "type": "integer" },
- { "type": "null" }
+ {
+ "type": "integer"
+ },
+ {
+ "type": "null"
+ }
],
"default": null,
"description": "Close the tab at this index. If no index is provided, use the focused tab's index."
@@ -785,12 +930,20 @@
"ScrollUpAction": {
"description": "Arguments for a scrollUp action",
"allOf": [
- { "$ref": "#/definitions/ShortcutAction" },
+ {
+ "$ref": "#/$defs/ShortcutAction"
+ },
{
"properties": {
- "action": { "type": "string", "pattern": "scrollUp" },
+ "action": {
+ "type": "string",
+ "pattern": "scrollUp"
+ },
"rowsToScroll": {
- "type": ["integer", "null"],
+ "type": [
+ "integer",
+ "null"
+ ],
"default": null,
"description": "Scroll up rowsToScroll lines. If no value is provided, use the system-level defaults."
}
@@ -801,12 +954,20 @@
"ScrollDownAction": {
"description": "Arguments for a scrollDown action",
"allOf": [
- { "$ref": "#/definitions/ShortcutAction" },
+ {
+ "$ref": "#/$defs/ShortcutAction"
+ },
{
"properties": {
- "action": { "type": "string", "pattern": "scrollDown" },
+ "action": {
+ "type": "string",
+ "pattern": "scrollDown"
+ },
"rowsToScroll": {
- "type": ["integer", "null"],
+ "type": [
+ "integer",
+ "null"
+ ],
"default": null,
"description": "Scroll down rowsToScroll lines. If no value is provided, use the system-level defaults."
}
@@ -817,28 +978,40 @@
"MoveTabAction": {
"description": "Arguments for moving a tab",
"allOf": [
- { "$ref": "#/definitions/ShortcutAction" },
+ {
+ "$ref": "#/$defs/ShortcutAction"
+ },
{
"properties": {
- "action": { "type": "string", "pattern": "moveTab" },
+ "action": {
+ "type": "string",
+ "pattern": "moveTab"
+ },
"direction": {
- "$ref": "#/definitions/MoveTabDirection",
+ "$ref": "#/$defs/MoveTabDirection",
"description": "The direction to move the tab"
}
}
}
],
- "required": [ "direction" ]
+ "required": [
+ "direction"
+ ]
},
"MultipleActionsAction": {
"description": "Arguments for the multiple actions command",
"allOf": [
- { "$ref": "#/definitions/ShortcutAction" },
+ {
+ "$ref": "#/$defs/ShortcutAction"
+ },
{
"properties": {
- "action": { "type": "string", "pattern": "multipleActions" },
- "actions" : {
- "$ref": "#/definitions/ShortcutAction",
+ "action": {
+ "type": "string",
+ "pattern": "multipleActions"
+ },
+ "actions": {
+ "$ref": "#/$defs/ShortcutAction",
"type": "array",
"minItems": 1,
"description": "A list of other actions."
@@ -846,17 +1019,24 @@
}
}
],
- "required": [ "actions" ]
- },
+ "required": [
+ "actions"
+ ]
+ },
"CommandPaletteAction": {
"description": "Arguments for a commandPalette action",
"allOf": [
- { "$ref": "#/definitions/ShortcutAction" },
+ {
+ "$ref": "#/$defs/ShortcutAction"
+ },
{
"properties": {
- "action": { "type": "string", "pattern": "commandPalette" },
+ "action": {
+ "type": "string",
+ "pattern": "commandPalette"
+ },
"launchMode": {
- "$ref": "#/definitions/CommandPaletteLaunchMode",
+ "$ref": "#/$defs/CommandPaletteLaunchMode",
"default": "action",
"description": "Toggle command palette in either action or command line mode. If no value is provided, the palette will launch in action mode."
}
@@ -867,28 +1047,42 @@
"FindMatchAction": {
"description": "Arguments corresponding to a Find Match Action",
"allOf": [
- { "$ref": "#/definitions/ShortcutAction" },
+ {
+ "$ref": "#/$defs/ShortcutAction"
+ },
{
"properties": {
- "action": { "type": "string", "pattern": "findMatch" },
+ "action": {
+ "type": "string",
+ "pattern": "findMatch"
+ },
"direction": {
- "$ref": "#/definitions/FindMatchDirection",
+ "$ref": "#/$defs/FindMatchDirection",
"default": "prev",
"description": "The direction to search in. \"prev\" will search upwards in the buffer, and \"next\" will search downwards."
}
}
}
],
- "required": [ "direction" ]
+ "required": [
+ "direction"
+ ]
},
"NewWindowAction": {
"description": "Arguments corresponding to a New Window Action",
"allOf": [
- { "$ref": "#/definitions/ShortcutAction" },
- { "$ref": "#/definitions/NewTerminalArgs" },
+ {
+ "$ref": "#/$defs/ShortcutAction"
+ },
+ {
+ "$ref": "#/$defs/NewTerminalArgs"
+ },
{
"properties": {
- "action": { "type":"string", "pattern": "newWindow" }
+ "action": {
+ "type": "string",
+ "pattern": "newWindow"
+ }
}
}
]
@@ -896,12 +1090,17 @@
"PrevTabAction": {
"description": "Arguments corresponding to a Previous Tab Action",
"allOf": [
- { "$ref": "#/definitions/ShortcutAction" },
+ {
+ "$ref": "#/$defs/ShortcutAction"
+ },
{
"properties": {
- "action": { "type":"string", "pattern": "prevTab" },
+ "action": {
+ "type": "string",
+ "pattern": "prevTab"
+ },
"tabSwitcherMode": {
- "$ref": "#/definitions/SwitchToAdjacentTabArgs",
+ "$ref": "#/$defs/SwitchToAdjacentTabArgs",
"default": null,
"description": "Move to the previous tab using \"tabSwitcherMode\". If no mode is provided, use the one globally defined one."
}
@@ -912,12 +1111,17 @@
"NextTabAction": {
"description": "Arguments corresponding to a Next Tab Action",
"allOf": [
- { "$ref": "#/definitions/ShortcutAction" },
+ {
+ "$ref": "#/$defs/ShortcutAction"
+ },
{
"properties": {
- "action": { "type":"string", "pattern": "nextTab" },
+ "action": {
+ "type": "string",
+ "pattern": "nextTab"
+ },
"tabSwitcherMode": {
- "$ref": "#/definitions/SwitchToAdjacentTabArgs",
+ "$ref": "#/$defs/SwitchToAdjacentTabArgs",
"default": null,
"description": "Move to the next tab using \"tabSwitcherMode\". If no mode is provided, use the one globally defined one."
}
@@ -928,10 +1132,15 @@
"RenameTabAction": {
"description": "Arguments corresponding to a renameTab Action",
"allOf": [
- { "$ref": "#/definitions/ShortcutAction" },
+ {
+ "$ref": "#/$defs/ShortcutAction"
+ },
{
"properties": {
- "action": { "type": "string", "pattern": "renameTab" },
+ "action": {
+ "type": "string",
+ "pattern": "renameTab"
+ },
"title": {
"type": "string",
"default": "",
@@ -944,10 +1153,15 @@
"RenameWindowAction": {
"description": "Arguments corresponding to a renameWindow Action",
"allOf": [
- { "$ref": "#/definitions/ShortcutAction" },
+ {
+ "$ref": "#/$defs/ShortcutAction"
+ },
{
"properties": {
- "action": { "type": "string", "pattern": "renameWindow" },
+ "action": {
+ "type": "string",
+ "pattern": "renameWindow"
+ },
"name": {
"type": "string",
"default": "",
@@ -960,13 +1174,19 @@
"FocusPaneAction": {
"description": "Arguments corresponding to a focusPane Action",
"allOf": [
- { "$ref": "#/definitions/ShortcutAction" },
+ {
+ "$ref": "#/$defs/ShortcutAction"
+ },
{
"properties": {
- "action": { "type": "string", "pattern": "focusPane" },
- "id": {
+ "action": {
"type": "string",
- "default": "",
+ "pattern": "focusPane"
+ },
+ "id": {
+ "type": "integer",
+ "minimum": 0,
+ "default": 0,
"description": "The ID of the pane to focus"
}
}
@@ -976,10 +1196,15 @@
"GlobalSummonAction": {
"description": "This is a special action that works globally in the OS, rather than only in the context of the terminal window. When pressed, this action will summon the terminal window.",
"allOf": [
- { "$ref": "#/definitions/ShortcutAction" },
+ {
+ "$ref": "#/$defs/ShortcutAction"
+ },
{
"properties": {
- "action": { "type": "string", "pattern": "globalSummon" },
+ "action": {
+ "type": "string",
+ "pattern": "globalSummon"
+ },
"desktop": {
"type": "string",
"default": "toCurrent",
@@ -1005,7 +1230,7 @@
"description": "When provided, summon the window whose name or ID matches the given name value. If no such window exists, then create a new window with that name."
},
"dropdownDuration": {
- "type": "number",
+ "type": "integer",
"minimum": 0,
"default": 0,
"description": "When provided with a positive number, \"slide\" the window in from the top of the screen using an animation that lasts dropdownDuration milliseconds."
@@ -1022,10 +1247,15 @@
"QuakeModeAction": {
"description": "This action is a special variation of the globalSummon action. It specifically summons a window called \"_quake\". If you would like to change the behavior of the quakeMode action, we recommended creating a new globalSummon entry.",
"allOf": [
- { "$ref": "#/definitions/ShortcutAction" },
+ {
+ "$ref": "#/$defs/ShortcutAction"
+ },
{
"properties": {
- "action": { "type": "string", "pattern": "quakeMode" }
+ "action": {
+ "type": "string",
+ "pattern": "quakeMode"
+ }
}
}
]
@@ -1035,56 +1265,120 @@
"properties": {
"command": {
"description": "The action executed when the associated key bindings are pressed.",
- "oneOf": [
- { "$ref": "#/definitions/AdjustFontSizeAction" },
- { "$ref": "#/definitions/CopyAction" },
- { "$ref": "#/definitions/ShortcutActionName" },
- { "$ref": "#/definitions/NewTabAction" },
- { "$ref": "#/definitions/SwitchToTabAction" },
- { "$ref": "#/definitions/MoveFocusAction" },
- { "$ref": "#/definitions/MovePaneAction" },
- { "$ref": "#/definitions/SwapPaneAction" },
- { "$ref": "#/definitions/ResizePaneAction" },
- { "$ref": "#/definitions/SendInputAction" },
- { "$ref": "#/definitions/SplitPaneAction" },
- { "$ref": "#/definitions/OpenSettingsAction" },
- { "$ref": "#/definitions/SetTabColorAction" },
- { "$ref": "#/definitions/SetColorSchemeAction" },
- { "$ref": "#/definitions/WtAction" },
- { "$ref": "#/definitions/CloseOtherTabsAction" },
- { "$ref": "#/definitions/CloseTabsAfterAction" },
- { "$ref": "#/definitions/CloseTabAction" },
- { "$ref": "#/definitions/ScrollUpAction" },
- { "$ref": "#/definitions/ScrollDownAction" },
- { "$ref": "#/definitions/MoveTabAction" },
- { "$ref": "#/definitions/FindMatchAction" },
- { "$ref": "#/definitions/NewWindowAction" },
- { "$ref": "#/definitions/NextTabAction" },
- { "$ref": "#/definitions/PrevTabAction" },
- { "$ref": "#/definitions/RenameTabAction" },
- { "$ref": "#/definitions/RenameWindowAction" },
- { "$ref": "#/definitions/FocusPaneAction" },
- { "$ref": "#/definitions/GlobalSummonAction" },
- { "$ref": "#/definitions/QuakeModeAction" },
- { "type": "null" }
- ]
+ "oneOf": [
+ {
+ "$ref": "#/$defs/AdjustFontSizeAction"
+ },
+ {
+ "$ref": "#/$defs/CopyAction"
+ },
+ {
+ "$ref": "#/$defs/ShortcutActionName"
+ },
+ {
+ "$ref": "#/$defs/NewTabAction"
+ },
+ {
+ "$ref": "#/$defs/SwitchToTabAction"
+ },
+ {
+ "$ref": "#/$defs/MoveFocusAction"
+ },
+ {
+ "$ref": "#/$defs/MovePaneAction"
+ },
+ {
+ "$ref": "#/$defs/SwapPaneAction"
+ },
+ {
+ "$ref": "#/$defs/ResizePaneAction"
+ },
+ {
+ "$ref": "#/$defs/SendInputAction"
+ },
+ {
+ "$ref": "#/$defs/SplitPaneAction"
+ },
+ {
+ "$ref": "#/$defs/OpenSettingsAction"
+ },
+ {
+ "$ref": "#/$defs/SetTabColorAction"
+ },
+ {
+ "$ref": "#/$defs/SetColorSchemeAction"
+ },
+ {
+ "$ref": "#/$defs/WtAction"
+ },
+ {
+ "$ref": "#/$defs/CloseOtherTabsAction"
+ },
+ {
+ "$ref": "#/$defs/CloseTabsAfterAction"
+ },
+ {
+ "$ref": "#/$defs/CloseTabAction"
+ },
+ {
+ "$ref": "#/$defs/ScrollUpAction"
+ },
+ {
+ "$ref": "#/$defs/ScrollDownAction"
+ },
+ {
+ "$ref": "#/$defs/MoveTabAction"
+ },
+ {
+ "$ref": "#/$defs/FindMatchAction"
+ },
+ {
+ "$ref": "#/$defs/NewWindowAction"
+ },
+ {
+ "$ref": "#/$defs/NextTabAction"
+ },
+ {
+ "$ref": "#/$defs/PrevTabAction"
+ },
+ {
+ "$ref": "#/$defs/RenameTabAction"
+ },
+ {
+ "$ref": "#/$defs/RenameWindowAction"
+ },
+ {
+ "$ref": "#/$defs/FocusPaneAction"
+ },
+ {
+ "$ref": "#/$defs/GlobalSummonAction"
+ },
+ {
+ "$ref": "#/$defs/QuakeModeAction"
+ },
+ {
+ "type": "null"
+ }
+ ]
},
"keys": {
"description": "Defines the key combinations used to call the command. It must be composed of...\n -any number of modifiers (ctrl/alt/shift)\n -a non-modifier key",
"oneOf": [
{
- "$ref": "#/definitions/KeyChordSegment"
+ "$ref": "#/$defs/KeyChordSegment"
},
{
"items": {
- "$ref": "#/definitions/KeyChordSegment"
+ "$ref": "#/$defs/KeyChordSegment"
},
"minItems": 1,
"type": "array"
}
]
},
- "icon": { "$ref": "#/definitions/Icon" },
+ "icon": {
+ "$ref": "#/$defs/Icon"
+ },
"name": {
"description": "The name that will appear in the command palette. If one isn't provided, the terminal will attempt to automatically generate a name.\nIf name is a string, it will be the name of the command.\nIf name is a object, the key property of the object will be used to lookup a localized string resource for the command",
"properties": {
@@ -1109,15 +1403,24 @@
"commands": {
"description": "List of commands to execute",
"items": {
- "$ref": "#/definitions/Keybinding/properties/command"
+ "$ref": "#/$defs/Keybinding/properties/command"
},
"minItems": 1,
"type": "array"
}
},
"anyOf": [
- {"required": ["name","commands"]},
- {"required": ["command"]}
+ {
+ "required": [
+ "name",
+ "commands"
+ ]
+ },
+ {
+ "required": [
+ "command"
+ ]
+ }
],
"type": "object"
},
@@ -1158,7 +1461,7 @@
"copyFormatting": {
"default": true,
"description": "When set to `true`, the color and font formatting of selected text is also copied to your clipboard. When set to `false`, only plain text is copied to your clipboard. An array of specific formats can also be used. Supported array values include `html` and `rtf`. Plain text is always copied.",
- "$ref": "#/definitions/CopyFormat"
+ "$ref": "#/$defs/CopyFormat"
},
"trimBlockSelection": {
"default": false,
@@ -1196,7 +1499,7 @@
"disabledProfileSources": {
"description": "Disables all the dynamic profile generators in this list, preventing them from adding their profiles to the list of profiles on startup.",
"items": {
- "$ref": "#/definitions/DynamicProfileSource"
+ "$ref": "#/$defs/DynamicProfileSource"
},
"type": "array"
},
@@ -1220,7 +1523,7 @@
"type": "integer"
},
"initialPosition": {
- "$ref": "#/definitions/Coordinates",
+ "$ref": "#/$defs/Coordinates",
"description": "The position of the top left corner of the window upon first load. On a system with multiple displays, these coordinates are relative to the top left of the primary display. If \"launchMode\" is set to \"maximized\" (or \"maximizedFocus\"), the window will be maximized on the monitor specified by those coordinates."
},
"initialRows": {
@@ -1261,7 +1564,10 @@
"description": "This parameter once allowed you to override the systemwide \"choose how many lines to scroll at one time\" setting. It no longer does so. However, you can customize the number of lines to scroll in \"scrollUp\" and \"scrollDown\" bindings.",
"maximum": 999,
"minimum": 0,
- "type": [ "integer", "string" ],
+ "type": [
+ "integer",
+ "string"
+ ],
"deprecated": true
},
"minimizeToNotificationArea": {
@@ -1274,23 +1580,28 @@
"description": "When set to true, the Terminal's notification icon will always be shown in the notification area.",
"type": "boolean"
},
+ "showAdminShield": {
+ "default": "true",
+ "description": "When set to true, the Terminal's tab row will display a shield icon when the Terminal is running with administrator privileges",
+ "type": "boolean"
+ },
"useAcrylicInTabRow": {
"default": "false",
"description": "When set to true, the tab row will have an acrylic background with 50% opacity.",
"type": "boolean"
},
- "actions": {
- "description": "Properties are specific to each custom action.",
- "items": {
- "$ref": "#/definitions/Keybinding"
- },
- "type": "array"
- },
+ "actions": {
+ "description": "Properties are specific to each custom action.",
+ "items": {
+ "$ref": "#/$defs/Keybinding"
+ },
+ "type": "array"
+ },
"keybindings": {
"description": "[deprecated] Use actions instead.",
"deprecated": true,
"items": {
- "$ref": "#/definitions/Keybinding"
+ "$ref": "#/$defs/Keybinding"
},
"type": "array"
},
@@ -1418,26 +1729,38 @@
"type": "string"
},
"background": {
- "$ref": "#/definitions/Color",
+ "$ref": "#/$defs/Color",
"default": "#0c0c0c",
"description": "Sets the background color of the text. Overrides \"background\" from the color scheme. Uses hex color format: \"#rrggbb\".",
- "type": ["string", "null"]
+ "type": [
+ "string",
+ "null"
+ ]
},
"unfocusedAppearance": {
- "$ref": "#/definitions/AppearanceConfig",
+ "$ref": "#/$defs/AppearanceConfig",
"description": "Sets the appearance of the terminal when it is unfocused.",
- "type": ["object", "null"]
+ "type": [
+ "object",
+ "null"
+ ]
},
"font": {
- "$ref": "#/definitions/FontConfig",
+ "$ref": "#/$defs/FontConfig",
"description": "Sets the font options of the terminal.",
- "type": ["object", "null"]
+ "type": [
+ "object",
+ "null"
+ ]
},
"backgroundImage": {
"description": "Sets the file location of the image to draw over the window background.",
"oneOf": [
{
- "type": ["string", null]
+ "type": [
+ "string",
+ "null"
+ ]
},
{
"enum": [
@@ -1445,7 +1768,10 @@
]
}
],
- "type": [ "string", "null" ]
+ "type": [
+ "string",
+ "null"
+ ]
},
"backgroundImageAlignment": {
"default": "center",
@@ -1484,7 +1810,7 @@
"bellStyle": {
"default": "audible",
"description": "Controls what happens when the application emits a BEL character. When set to \"all\", the Terminal will play a sound, flash the taskbar icon (if the terminal window is not in focus) and flash the window. An array of specific behaviors can also be used. Supported array values include `audible`, `window` and `taskbar`. When set to \"none\", nothing will happen.",
- "$ref": "#/definitions/BellStyle"
+ "$ref": "#/$defs/BellStyle"
},
"closeOnExit": {
"default": "graceful",
@@ -1514,8 +1840,12 @@
},
"cursorColor": {
"oneOf": [
- { "$ref": "#/definitions/Color" },
- {"type": "null"}
+ {
+ "$ref": "#/$defs/Color"
+ },
+ {
+ "type": "null"
+ }
],
"description": "Sets the color of the cursor. Overrides the cursor color from the color scheme. Uses hex color format: \"#rrggbb\"."
},
@@ -1523,7 +1853,10 @@
"description": "Sets the percentage height of the cursor starting from the bottom. Only works when cursorShape is set to \"vintage\". Accepts values from 1-100.",
"maximum": 100,
"minimum": 1,
- "type": ["integer","null"],
+ "type": [
+ "integer",
+ "null"
+ ],
"default": 25
},
"cursorShape": {
@@ -1589,13 +1922,16 @@
"deprecated": true
},
"foreground": {
- "$ref": "#/definitions/Color",
+ "$ref": "#/$defs/Color",
"default": "#cccccc",
"description": "Sets the text color. Overrides \"foreground\" from the color scheme. Uses hex color format: \"#rrggbb\".",
- "type": ["string", "null"]
+ "type": [
+ "string",
+ "null"
+ ]
},
"guid": {
- "$ref": "#/definitions/ProfileGuid",
+ "$ref": "#/$defs/ProfileGuid",
"description": "Unique identifier of the profile. Written in registry format: \"{00000000-0000-0000-0000-000000000000}\"."
},
"hidden": {
@@ -1609,7 +1945,9 @@
"minimum": -1,
"type": "integer"
},
- "icon":{ "$ref": "#/definitions/Icon" },
+ "icon": {
+ "$ref": "#/$defs/Icon"
+ },
"name": {
"description": "Name of the profile. Displays in the dropdown menu.",
"minLength": 1,
@@ -1646,8 +1984,12 @@
},
"selectionBackground": {
"oneOf": [
- {"$ref": "#/definitions/Color"},
- { "type": "null" }
+ {
+ "$ref": "#/$defs/Color"
+ },
+ {
+ "type": "null"
+ }
],
"description": "Sets the background color of selected text. Overrides selectionBackground set in the color scheme. Uses hex color format: \"#rrggbb\"."
},
@@ -1663,7 +2005,10 @@
},
"source": {
"description": "Stores the name of the profile generator that originated this profile.",
- "type": ["string", "null"]
+ "type": [
+ "string",
+ "null"
+ ]
},
"startingDirectory": {
"description": "The directory the shell starts in when it is loaded.",
@@ -1675,13 +2020,19 @@
"default": false
},
"tabColor": {
- "$ref": "#/definitions/Color",
+ "$ref": "#/$defs/Color",
"description": "Sets the color of the profile's tab. Using the tab color picker will override this color.",
- "type": ["string", "null"]
+ "type": [
+ "string",
+ "null"
+ ]
},
"tabTitle": {
"description": "If set, will replace the name as the title to pass to the shell on startup. Some shells (like bash) may choose to ignore this initial value, while others (cmd, powershell) may use this value over the lifetime of the application.",
- "type": ["string", "null"]
+ "type": [
+ "string",
+ "null"
+ ]
},
"useAcrylic": {
"default": false,
@@ -1694,7 +2045,7 @@
"ProfileList": {
"description": "A list of profiles and the properties specific to each.",
"items": {
- "$ref": "#/definitions/Profile",
+ "$ref": "#/$defs/Profile",
"required": [
"guid",
"name"
@@ -1706,11 +2057,11 @@
"description": "A list of profiles and default settings that apply to all of them",
"properties": {
"list": {
- "$ref": "#/definitions/ProfileList"
+ "$ref": "#/$defs/ProfileList"
},
"defaults": {
"description": "The default settings that apply to every profile.",
- "$ref": "#/definitions/Profile"
+ "$ref": "#/$defs/Profile"
}
},
"type": "object"
@@ -1726,84 +2077,84 @@
"type": "string"
},
"background": {
- "$ref": "#/definitions/Color",
+ "$ref": "#/$defs/Color",
"description": "Sets the background color of the color scheme."
},
"black": {
- "$ref": "#/definitions/Color",
+ "$ref": "#/$defs/Color",
"description": "Sets the color used as ANSI black."
},
"blue": {
- "$ref": "#/definitions/Color",
+ "$ref": "#/$defs/Color",
"description": "Sets the color used as ANSI blue."
},
"brightBlack": {
- "$ref": "#/definitions/Color",
+ "$ref": "#/$defs/Color",
"description": "Sets the color used as ANSI bright black."
},
"brightBlue": {
- "$ref": "#/definitions/Color",
+ "$ref": "#/$defs/Color",
"description": "Sets the color used as ANSI bright blue."
},
"brightCyan": {
- "$ref": "#/definitions/Color",
+ "$ref": "#/$defs/Color",
"description": "Sets the color used as ANSI bright cyan."
},
"brightGreen": {
- "$ref": "#/definitions/Color",
+ "$ref": "#/$defs/Color",
"description": "Sets the color used as ANSI bright green."
},
"brightPurple": {
- "$ref": "#/definitions/Color",
+ "$ref": "#/$defs/Color",
"description": "Sets the color used as ANSI bright purple."
},
"brightRed": {
- "$ref": "#/definitions/Color",
+ "$ref": "#/$defs/Color",
"description": "Sets the color used as ANSI bright red."
},
"brightWhite": {
- "$ref": "#/definitions/Color",
+ "$ref": "#/$defs/Color",
"description": "Sets the color used as ANSI bright white."
},
"brightYellow": {
- "$ref": "#/definitions/Color",
+ "$ref": "#/$defs/Color",
"description": "Sets the color used as ANSI bright yellow."
},
"cursorColor": {
- "$ref": "#/definitions/Color",
+ "$ref": "#/$defs/Color",
"default": "#FFFFFF",
"description": "Sets the cursor color of the color scheme."
},
"cyan": {
- "$ref": "#/definitions/Color",
+ "$ref": "#/$defs/Color",
"description": "Sets the color used as ANSI cyan."
},
"foreground": {
- "$ref": "#/definitions/Color",
+ "$ref": "#/$defs/Color",
"description": "Sets the foreground color of the color scheme."
},
"green": {
- "$ref": "#/definitions/Color",
+ "$ref": "#/$defs/Color",
"description": "Sets the color used as ANSI green."
},
"purple": {
- "$ref": "#/definitions/Color",
+ "$ref": "#/$defs/Color",
"description": "Sets the color used as ANSI purple."
},
"red": {
- "$ref": "#/definitions/Color",
+ "$ref": "#/$defs/Color",
"description": "Sets the color used as ANSI red."
},
"selectionBackground": {
- "$ref": "#/definitions/Color",
+ "$ref": "#/$defs/Color",
"description": "Sets the selection background color of the color scheme."
},
"white": {
- "$ref": "#/definitions/Color",
+ "$ref": "#/$defs/Color",
"description": "Sets the color used as ANSI white."
},
"yellow": {
- "$ref": "#/definitions/Color",
+ "$ref": "#/$defs/Color",
"description": "Sets the color used as ANSI yellow."
}
},
@@ -1813,17 +2164,25 @@
}
},
"allOf": [
- { "$ref": "#/definitions/Globals" },
+ {
+ "$ref": "#/$defs/Globals"
+ },
{
"additionalItems": true,
"properties": {
"profiles": {
"oneOf": [
- { "$ref": "#/definitions/ProfileList" },
- { "$ref": "#/definitions/ProfilesObject" }
+ {
+ "$ref": "#/$defs/ProfileList"
+ },
+ {
+ "$ref": "#/$defs/ProfilesObject"
+ }
]
},
- "schemes": { "$ref": "#/definitions/SchemeList" }
+ "schemes": {
+ "$ref": "#/$defs/SchemeList"
+ }
},
"required": [
"profiles",
diff --git a/doc/specs/Keyboard-Selection.md b/doc/specs/Keyboard-Selection.md
new file mode 100644
index 000000000..f9954fca7
--- /dev/null
+++ b/doc/specs/Keyboard-Selection.md
@@ -0,0 +1,171 @@
+---
+author: Carlos Zamora @carlos-zamora
+created on: 2019-08-30
+last updated: 2021-09-17
+issue id: 715
+---
+
+# Keyboard Selection
+
+## Abstract
+
+This spec describes a new set of non-configurable keybindings that allows the user to update a selection without the use of a mouse or stylus.
+
+## Inspiration
+
+ConHost allows the user to modify a selection using the keyboard. Holding `Shift` allows the user to move the second selection endpoint in accordance with the arrow keys. The selection endpoint updates by one cell per key event, allowing the user to refine the selected region.
+
+Mark mode allows the user to create a selection using only the keyboard, then edit it as mentioned above.
+
+
+## Solution Design
+
+The fundamental solution design for keyboard selection is that the responsibilities between the Terminal Control and Terminal Core must be very distinct. The Terminal Control is responsible for handling user interaction and directing the Terminal Core to update the selection. The Terminal Core will need to update the selection according to the preferences of the Terminal Control.
+
+Relatively recently, TerminalControl was split into `TerminalControl`, `ControlInteractivity`, and `ControlCore`. Changes made to `ControlInteractivity`, `ControlCore`, and below propagate functionality to all consumers, meaning that the WPF terminal would benefit from these changes with no additional work required.
+
+### Fundamental Terminal Control Changes
+
+`ControlCore::TrySendKeyEvent()` is responsible for handling the key events after key bindings are dealt with in `TermControl`. At the time of writing this spec, there are 2 cases handled in this order:
+- Clear the selection (except in a few key scenarios)
+- Send Key Event
+
+The first branch will be updated to _modify_ the selection instead of usually _clearing_ it. This will happen by converting the key event into parameters to forward to `TerminalCore`, which then updates the selection appropriately.
+
+#### Idea: Make keyboard selection a collection of standard keybindings
+One idea is to introduce an `updateSelection` action that conditionally works if a selection is active (similar to the `copy` action). For these key bindings, if there is no selection, the key events are forwarded to the application.
+
+Thanks to Keybinding Args, there would only be 1 new command:
+| Action | Keybinding Args | Description |
+|--|--|--|
+| `updateSelection` | | If a selection exists, moves the last selection endpoint. |
+| | `Enum direction { up, down, left, right }` | The direction the selection will be moved in. |
+| | `Enum mode { char, word, view, buffer }` | The context for which to move the selection endpoint to. (defaults to `char`) |
+
+
+By default, the following keybindings will be set:
+```JS
+// Character Selection
+{ "command": {"action": "updateSelection", "direction": "left", "mode": "char" }, "keys": "shift+left" },
+{ "command": {"action": "updateSelection", "direction": "right", "mode": "char" }, "keys": "shift+right" },
+{ "command": {"action": "updateSelection", "direction": "up", "mode": "char" }, "keys": "shift+up" },
+{ "command": {"action": "updateSelection", "direction": "down", "mode": "char" }, "keys": "shift+down" },
+
+// Word Selection
+{ "command": {"action": "updateSelection", "direction": "left", "mode": "word" }, "keys": "ctrl+shift+left" },
+{ "command": {"action": "updateSelection", "direction": "right", "mode": "word" }, "keys": "ctrl+shift+right" },
+
+// Viewport Selection
+{ "command": {"action": "updateSelection", "direction": "left", "mode": "view" }, "keys": "shift+home" },
+{ "command": {"action": "updateSelection", "direction": "right", "mode": "view" }, "keys": "shift+end" },
+{ "command": {"action": "updateSelection", "direction": "up", "mode": "view" }, "keys": "shift+pgup" },
+{ "command": {"action": "updateSelection", "direction": "down", "mode": "view" }, "keys": "shift+pgdn" },
+
+// Buffer Corner Selection
+{ "command": {"action": "updateSelection", "direction": "up", "mode": "buffer" }, "keys": "ctrl+shift+home" },
+{ "command": {"action": "updateSelection", "direction": "down", "mode": "buffer" }, "keys": "ctrl+shift+end" },
+```
+These are in accordance with ConHost's keyboard selection model.
+
+This idea was abandoned due to several reasons:
+1. Keyboard selection should be a standard way to interact with a terminal across all consumers (i.e. WPF control, etc.)
+2. There isn't really another set of key bindings that makes sense for this. We already hardcoded ESC as a way to clear the selection. This is just an extension of that.
+3. Adding 12 conditionally effective key bindings takes the spot of 12 potential non-conditional key bindings. It would be nice if a different key binding could be set when the selection is not active, but that makes the settings design much more complicated.
+4. 12 new items in the command palette is also pretty excessive.
+5. If proven wrong when this is in WT Preview, we can revisit this and make them customizable then. It's better to add the ability to customize it later than take it away.
+
+#### Idea: Make keyboard selection a simulation of mouse selection
+It may seem that some effort can be saved by making the keyboard selection act as a simulation of mouse selection. There is a union of mouse and keyboard activity that can be represented in a single set of selection motion interfaces that are commanded by the TermControl's Mouse/Keyboard handler and adapted into appropriate motions in the Terminal Core.
+
+However, the mouse handler operates by translating a pixel coordinate on the screen to a text buffer coordinate. This would have to be rewritten and the approach was deemed unworthy.
+
+
+### Fundamental Terminal Core Changes
+
+The Terminal Core will need to expose a `UpdateSelection()` function that is called by the keybinding handler. The following parameters will need to be passed in:
+- `enum SelectionDirection`: the direction that the selection endpoint will attempt to move to. Possible values include `Up`, `Down`, `Left`, and `Right`.
+- `enum SelectionExpansion`: the selection expansion mode that the selection endpoint will adhere to. Possible values include `Char`, `Word`, `View`, `Buffer`.
+
+#### Moving by Cell
+For `SelectionExpansion = Char`, the selection endpoint will be updated according to the buffer's output pattern. For **horizontal movements**, the selection endpoint will attempt to move left or right. If a viewport boundary is hit, the endpoint will wrap appropriately (i.e.: hitting the left boundary moves it to the last cell of the line above it).
+
+For **vertical movements**, the selection endpoint will attempt to move up or down. If a **viewport boundary** is hit and there is a scroll buffer, the endpoint will move and scroll accordingly by a line.
+
+If a **buffer boundary** is hit, the endpoint will not move. In this case, however, the event will still be considered handled.
+
+**NOTE**: An important thing to handle properly in all cases is wide glyphs. The user should not be allowed to select a portion of a wide glyph; it should be all or none of it. When calling `_ExpandWideGlyphSelection` functions, the result must be saved to the endpoint.
+
+#### Moving by Word
+For `SelectionExpansion = Word`, the selection endpoint will also be updated according to the buffer's output pattern, as above. However, the selection will be updated in accordance with "chunk selection" (performing a double-click and dragging the mouse to expand the selection). For **horizontal movements**, the selection endpoint will be updated according to the `_ExpandDoubleClickSelection` functions. The result must be saved to the endpoint. As before, if a boundary is hit, the endpoint will wrap appropriately. See [Future Considerations](#FutureConsiderations) for how this will interact with line wrapping.
+
+For **vertical movements**, the movement is a little more complicated than before. The selection will still respond to buffer and viewport boundaries as before. If the user is trying to move up, the selection endpoint will attempt to move up by one line, then selection will be expanded leftwards. Alternatively, if the user is trying to move down, the selection endpoint will attempt to move down by one line, then the selection will be expanded rightwards.
+
+#### Moving by Viewport
+For `SelectionExpansion = View`, the selection endpoint will be updated according to the viewport's height. Horizontal movements will be updated according to the viewport's width, thus resulting in the endpoint being moved to the left/right boundary of the viewport.
+
+#### Moving by Buffer
+
+For `SelectionExpansion = Buffer`, the selection endpoint will be moved to the beginning or end of all the text within the buffer. If moving up or left, set the position to 0,0 (the origin of the buffer). If moving down or right, set the position to the last character in the buffer.
+
+
+**NOTE**: In all cases, horizontal movements attempting to move past the left/right viewport boundaries result in a wrap. Vertical movements attempting to move past the top/bottom viewport boundaries will scroll such that the selection is at the edge of the screen. Vertical movements attempting to move past the top/bottom buffer boundaries will be clamped to be within buffer boundaries.
+
+Every combination of the `SelectionDirection` and `SelectionExpansion` will map to a keybinding. These pairings are shown below in the UI/UX Design --> Keybindings section.
+
+**NOTE**: If `copyOnSelect` is enabled, we need to make sure we **DO NOT** update the clipboard on every change in selection. The user must explicitly choose to copy the selected text from the buffer.
+
+
+## UI/UX Design
+
+### Key Bindings
+
+There will only be 1 new command that needs to be added:
+| Action | Keybinding Args | Description |
+|--|--|--|
+| `selectAll` | | Select the entire text buffer.
+
+By default, the following key binding will be set:
+```JS
+{ "command": "selectAll", "keys": "ctrl+shift+a" },
+```
+
+## Capabilities
+
+### Accessibility
+
+Using the keyboard is generally a more accessible experience than using the mouse. Being able to modify a selection by using the keyboard is a good first step towards making selecting text more accessible.
+
+### Security
+
+N/A
+
+### Reliability
+
+With regards to the Terminal Core, the newly introduced code should rely on already existing and tested code. Thus no crash-related bugs are expected.
+
+With regards to Terminal Control and the settings model, crash-related bugs are not expected. However, ensuring that the selection is updated and cleared in general use-case scenarios must be ensured.
+
+### Compatibility
+
+N/A
+
+### Performance, Power, and Efficiency
+
+## Potential Issues
+
+### Grapheme Clusters
+When grapheme cluster support is inevitably added to the Text Buffer, moving by "cell" is expected to move by "character" or "cluster". This is similar to how wide glyphs are handled today. Either all of it is selected, or none of it.
+
+## Future considerations
+
+### Word Selection Wrap
+At the time of writing this spec, expanding or moving by word is interrupted by the beginning or end of the line, regardless of the wrap flag being set. In the future, selection and the accessibility models will respect the wrap flag on the text buffer.
+
+## Mark Mode
+
+This functionality will be expanded to create a feature similar to Mark Mode. This will allow a user to create a selection using only the keyboard.
+
+
+## Resources
+
+- https://blogs.windows.com/windowsdeveloper/2014/10/07/console-improvements-in-the-windows-10-technical-preview/
diff --git a/src/Terminal.wprp b/src/Terminal.wprp
index d37c749c9..80a6e730b 100644
--- a/src/Terminal.wprp
+++ b/src/Terminal.wprp
@@ -12,6 +12,7 @@
+
@@ -23,6 +24,7 @@
+
diff --git a/src/buffer/out/textBuffer.cpp b/src/buffer/out/textBuffer.cpp
index 466e38ecf..3fba7b082 100644
--- a/src/buffer/out/textBuffer.cpp
+++ b/src/buffer/out/textBuffer.cpp
@@ -1430,12 +1430,13 @@ const til::point TextBuffer::GetGlyphStart(const til::point pos, std::optional limitOptional) const
+const til::point TextBuffer::GetGlyphEnd(const til::point pos, bool accessibilityMode, std::optional limitOptional) const
{
COORD resultPos = pos;
const auto bufferSize = GetSize();
@@ -1453,7 +1454,10 @@ const til::point TextBuffer::GetGlyphEnd(const til::point pos, std::optional limitOptional = std::nullopt) const;
- const til::point GetGlyphEnd(const til::point pos, std::optional limitOptional = std::nullopt) const;
+ const til::point GetGlyphEnd(const til::point pos, bool accessibilityMode = false, std::optional limitOptional = std::nullopt) const;
bool MoveToNextGlyph(til::point& pos, bool allowBottomExclusive = false, std::optional limitOptional = std::nullopt) const;
bool MoveToPreviousGlyph(til::point& pos, std::optional limitOptional = std::nullopt) const;
diff --git a/src/cascadia/LocalTests_SettingsModel/CommandTests.cpp b/src/cascadia/LocalTests_SettingsModel/CommandTests.cpp
index b25d476e7..da5e3916c 100644
--- a/src/cascadia/LocalTests_SettingsModel/CommandTests.cpp
+++ b/src/cascadia/LocalTests_SettingsModel/CommandTests.cpp
@@ -465,6 +465,10 @@ namespace SettingsModelLocalTests
"name":"action7_startingDirectoryWithTrailingSlash",
"command": { "action": "newWindow", "startingDirectory":"C:\\", "commandline": "bar.exe" }
},
+ {
+ "name":"action8_tabTitleEscaping",
+ "command": { "action": "newWindow", "tabTitle":"\\\";foo\\" }
+ }
])" };
const auto commands0Json = VerifyParseSucceeded(commands0String);
@@ -473,7 +477,7 @@ namespace SettingsModelLocalTests
VERIFY_ARE_EQUAL(0u, commands.Size());
auto warnings = implementation::Command::LayerJson(commands, commands0Json);
VERIFY_ARE_EQUAL(0u, warnings.size());
- VERIFY_ARE_EQUAL(8u, commands.Size());
+ VERIFY_ARE_EQUAL(9u, commands.Size());
{
auto command = commands.Lookup(L"action0");
@@ -586,5 +590,20 @@ namespace SettingsModelLocalTests
L"cmdline: \"%s\"", cmdline.c_str()));
VERIFY_ARE_EQUAL(L"--startingDirectory \"C:\\\\\" -- \"bar.exe\"", terminalArgs.ToCommandline());
}
+
+ {
+ auto command = commands.Lookup(L"action8_tabTitleEscaping");
+ VERIFY_IS_NOT_NULL(command);
+ VERIFY_IS_NOT_NULL(command.ActionAndArgs());
+ VERIFY_ARE_EQUAL(ShortcutAction::NewWindow, command.ActionAndArgs().Action());
+ const auto& realArgs = command.ActionAndArgs().Args().try_as();
+ VERIFY_IS_NOT_NULL(realArgs);
+ const auto& terminalArgs = realArgs.TerminalArgs();
+ VERIFY_IS_NOT_NULL(terminalArgs);
+ auto cmdline = terminalArgs.ToCommandline();
+ Log::Comment(NoThrowString().Format(
+ L"cmdline: \"%s\"", cmdline.c_str()));
+ VERIFY_ARE_EQUAL(LR"-(--title "\\\"\;foo\\")-", terminalArgs.ToCommandline());
+ }
}
}
diff --git a/src/cascadia/LocalTests_TerminalApp/TabTests.cpp b/src/cascadia/LocalTests_TerminalApp/TabTests.cpp
index 4e3da70aa..ecb40c3eb 100644
--- a/src/cascadia/LocalTests_TerminalApp/TabTests.cpp
+++ b/src/cascadia/LocalTests_TerminalApp/TabTests.cpp
@@ -751,7 +751,7 @@ namespace TerminalAppLocalTests
});
VERIFY_SUCCEEDED(result);
- Log::Comment(L"Move focus. This will cause us to un-zoom.");
+ Log::Comment(L"Move focus. We should still be zoomed.");
result = RunOnUIThread([&page]() {
// Set up action
MoveFocusArgs args{ FocusDirection::Left };
@@ -761,7 +761,7 @@ namespace TerminalAppLocalTests
auto firstTab = page->_GetTerminalTabImpl(page->_tabs.GetAt(0));
VERIFY_ARE_EQUAL(2, firstTab->GetLeafPaneCount());
- VERIFY_IS_FALSE(firstTab->IsZoomed());
+ VERIFY_IS_TRUE(firstTab->IsZoomed());
});
VERIFY_SUCCEEDED(result);
}
@@ -1357,7 +1357,8 @@ namespace TerminalAppLocalTests
Log::Comment(L"Color should be changed to the preview");
VERIFY_ARE_EQUAL(til::color{ 0xff000000 }, controlSettings.DefaultBackground());
- VERIFY_ARE_EQUAL(originalSettings, page->_originalSettings);
+ // And we should have stored a function to revert the change.
+ VERIFY_ARE_EQUAL(1u, page->_restorePreviewFuncs.size());
});
TestOnUIThread([&page]() {
@@ -1383,7 +1384,8 @@ namespace TerminalAppLocalTests
Log::Comment(L"Color should be changed");
VERIFY_ARE_EQUAL(til::color{ 0xff000000 }, controlSettings.DefaultBackground());
- VERIFY_ARE_EQUAL(nullptr, page->_originalSettings);
+ // After preview there should be no more restore functions to execute.
+ VERIFY_ARE_EQUAL(0u, page->_restorePreviewFuncs.size());
});
}
@@ -1428,7 +1430,6 @@ namespace TerminalAppLocalTests
Log::Comment(L"Color should be changed to the preview");
VERIFY_ARE_EQUAL(til::color{ 0xff000000 }, controlSettings.DefaultBackground());
- VERIFY_ARE_EQUAL(originalSettings, page->_originalSettings);
});
TestOnUIThread([&page]() {
@@ -1451,7 +1452,6 @@ namespace TerminalAppLocalTests
Log::Comment(L"Color should be the same as it originally was");
VERIFY_ARE_EQUAL(til::color{ 0xff0c0c0c }, controlSettings.DefaultBackground());
- VERIFY_ARE_EQUAL(nullptr, page->_originalSettings);
});
}
@@ -1498,7 +1498,6 @@ namespace TerminalAppLocalTests
Log::Comment(L"Color should be changed to the preview");
VERIFY_ARE_EQUAL(til::color{ 0xff000000 }, controlSettings.DefaultBackground());
- VERIFY_ARE_EQUAL(originalSettings, page->_originalSettings);
});
TestOnUIThread([&page]() {
@@ -1522,7 +1521,6 @@ namespace TerminalAppLocalTests
Log::Comment(L"Color should be changed to the preview");
VERIFY_ARE_EQUAL(til::color{ 0xffFAFAFA }, controlSettings.DefaultBackground());
- VERIFY_ARE_EQUAL(originalSettings, page->_originalSettings);
});
TestOnUIThread([&page]() {
@@ -1548,7 +1546,6 @@ namespace TerminalAppLocalTests
Log::Comment(L"Color should be changed");
VERIFY_ARE_EQUAL(til::color{ 0xffFAFAFA }, controlSettings.DefaultBackground());
- VERIFY_ARE_EQUAL(nullptr, page->_originalSettings);
});
}
diff --git a/src/cascadia/PublicTerminalCore/HwndTerminal.cpp b/src/cascadia/PublicTerminalCore/HwndTerminal.cpp
index c86f5d621..02025be81 100644
--- a/src/cascadia/PublicTerminalCore/HwndTerminal.cpp
+++ b/src/cascadia/PublicTerminalCore/HwndTerminal.cpp
@@ -549,11 +549,11 @@ try
if (multiClickMapper == 3)
{
- _terminal->MultiClickSelection(cursorPosition / fontSize, ::Terminal::SelectionExpansionMode::Line);
+ _terminal->MultiClickSelection(cursorPosition / fontSize, ::Terminal::SelectionExpansion::Line);
}
else if (multiClickMapper == 2)
{
- _terminal->MultiClickSelection(cursorPosition / fontSize, ::Terminal::SelectionExpansionMode::Word);
+ _terminal->MultiClickSelection(cursorPosition / fontSize, ::Terminal::SelectionExpansion::Word);
}
else
{
diff --git a/src/cascadia/Remoting/GetWindowLayoutArgs.cpp b/src/cascadia/Remoting/GetWindowLayoutArgs.cpp
new file mode 100644
index 000000000..f2cc01df4
--- /dev/null
+++ b/src/cascadia/Remoting/GetWindowLayoutArgs.cpp
@@ -0,0 +1,5 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT license.
+#include "pch.h"
+#include "GetWindowLayoutArgs.h"
+#include "GetWindowLayoutArgs.g.cpp"
diff --git a/src/cascadia/Remoting/GetWindowLayoutArgs.h b/src/cascadia/Remoting/GetWindowLayoutArgs.h
new file mode 100644
index 000000000..06706f60b
--- /dev/null
+++ b/src/cascadia/Remoting/GetWindowLayoutArgs.h
@@ -0,0 +1,32 @@
+/*++
+Copyright (c) Microsoft Corporation
+Licensed under the MIT license.
+
+Class Name:
+- GetWindowLayoutArgs.h
+
+Abstract:
+- This is a helper class for getting the window layout from a peasant.
+ Depending on if we are running on the monarch or on a peasant we might need
+ to switch what thread we are executing on. This gives us the option of
+ either returning the json result synchronously, or as a promise.
+--*/
+
+#pragma once
+
+#include "GetWindowLayoutArgs.g.h"
+#include "../cascadia/inc/cppwinrt_utils.h"
+
+namespace winrt::Microsoft::Terminal::Remoting::implementation
+{
+ struct GetWindowLayoutArgs : public GetWindowLayoutArgsT
+ {
+ WINRT_PROPERTY(winrt::hstring, WindowLayoutJson, L"");
+ WINRT_PROPERTY(winrt::Windows::Foundation::IAsyncOperation, WindowLayoutJsonAsync, nullptr)
+ };
+}
+
+namespace winrt::Microsoft::Terminal::Remoting::factory_implementation
+{
+ BASIC_FACTORY(GetWindowLayoutArgs);
+}
diff --git a/src/cascadia/Remoting/Microsoft.Terminal.RemotingLib.vcxproj b/src/cascadia/Remoting/Microsoft.Terminal.RemotingLib.vcxproj
index a2d6e8ae6..517c2f56f 100644
--- a/src/cascadia/Remoting/Microsoft.Terminal.RemotingLib.vcxproj
+++ b/src/cascadia/Remoting/Microsoft.Terminal.RemotingLib.vcxproj
@@ -12,7 +12,6 @@
-
@@ -36,6 +35,12 @@
Peasant.idl
+
+ Peasant.idl
+
+
+ Monarch.idl
+
@@ -71,6 +76,12 @@
Peasant.idl
+
+ Peasant.idl
+
+
+ Monarch.idl
+ Create
@@ -128,6 +139,5 @@
-
-
+
\ No newline at end of file
diff --git a/src/cascadia/Remoting/Monarch.cpp b/src/cascadia/Remoting/Monarch.cpp
index c16eb52e9..eed247ab4 100644
--- a/src/cascadia/Remoting/Monarch.cpp
+++ b/src/cascadia/Remoting/Monarch.cpp
@@ -6,6 +6,7 @@
#include "Monarch.h"
#include "CommandlineArgs.h"
#include "FindTargetWindowArgs.h"
+#include "QuitAllRequestedArgs.h"
#include "ProposeCommandlineResult.h"
#include "Monarch.g.cpp"
@@ -135,12 +136,18 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
// - used
// Return Value:
// -
- void Monarch::_handleQuitAll(const winrt::Windows::Foundation::IInspectable& /*sender*/,
- const winrt::Windows::Foundation::IInspectable& /*args*/)
+ winrt::fire_and_forget Monarch::_handleQuitAll(const winrt::Windows::Foundation::IInspectable& /*sender*/,
+ const winrt::Windows::Foundation::IInspectable& /*args*/)
{
// Let the process hosting the monarch run any needed logic before
// closing all windows.
- _QuitAllRequestedHandlers(*this, nullptr);
+ auto args = winrt::make_self();
+ _QuitAllRequestedHandlers(*this, *args);
+
+ if (const auto action = args->BeforeQuitAllAction())
+ {
+ co_await action;
+ }
_quitting.store(true);
// Tell all peasants to exit.
@@ -994,4 +1001,28 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
_forEachPeasant(func, onError);
}
+
+ // Method Description:
+ // - Ask all peasants to return their window layout as json
+ // Arguments:
+ // -
+ // Return Value:
+ // - The collection of window layouts from each peasant.
+ Windows::Foundation::Collections::IVector Monarch::GetAllWindowLayouts()
+ {
+ std::vector vec;
+ auto callback = [&](const auto& /*id*/, const auto& p) {
+ vec.emplace_back(p.GetWindowLayout());
+ };
+ auto onError = [](auto&& id) {
+ TraceLoggingWrite(g_hRemotingProvider,
+ "Monarch_GetAllWindowLayouts_Failed",
+ TraceLoggingInt64(id, "peasantID", "The ID of the peasant which we could not get a window layout from"),
+ TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE),
+ TraceLoggingKeyword(TIL_KEYWORD_TRACE));
+ };
+ _forEachPeasant(callback, onError);
+
+ return winrt::single_threaded_vector(std::move(vec));
+ }
}
diff --git a/src/cascadia/Remoting/Monarch.h b/src/cascadia/Remoting/Monarch.h
index 7ec904499..b965d1d2a 100644
--- a/src/cascadia/Remoting/Monarch.h
+++ b/src/cascadia/Remoting/Monarch.h
@@ -59,13 +59,14 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
void SummonAllWindows();
bool DoesQuakeWindowExist();
Windows::Foundation::Collections::IVectorView GetPeasantInfos();
+ Windows::Foundation::Collections::IVector GetAllWindowLayouts();
TYPED_EVENT(FindTargetWindowRequested, winrt::Windows::Foundation::IInspectable, winrt::Microsoft::Terminal::Remoting::FindTargetWindowArgs);
TYPED_EVENT(ShowNotificationIconRequested, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
TYPED_EVENT(HideNotificationIconRequested, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
TYPED_EVENT(WindowCreated, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
TYPED_EVENT(WindowClosed, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
- TYPED_EVENT(QuitAllRequested, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
+ TYPED_EVENT(QuitAllRequested, winrt::Windows::Foundation::IInspectable, winrt::Microsoft::Terminal::Remoting::QuitAllRequestedArgs);
private:
uint64_t _ourPID;
@@ -103,8 +104,8 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
void _renameRequested(const winrt::Windows::Foundation::IInspectable& sender,
const winrt::Microsoft::Terminal::Remoting::RenameRequestArgs& args);
- void _handleQuitAll(const winrt::Windows::Foundation::IInspectable& sender,
- const winrt::Windows::Foundation::IInspectable& args);
+ winrt::fire_and_forget _handleQuitAll(const winrt::Windows::Foundation::IInspectable& sender,
+ const winrt::Windows::Foundation::IInspectable& args);
// Method Description:
// - Helper for doing something on each and every peasant.
@@ -177,6 +178,10 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
}
}
_clearOldMruEntries(peasantsToErase);
+
+ // A peasant died, let the app host know that the number of
+ // windows has changed.
+ _WindowClosedHandlers(nullptr, nullptr);
}
}
diff --git a/src/cascadia/Remoting/Monarch.idl b/src/cascadia/Remoting/Monarch.idl
index 4eb77695a..f60b3997a 100644
--- a/src/cascadia/Remoting/Monarch.idl
+++ b/src/cascadia/Remoting/Monarch.idl
@@ -31,6 +31,12 @@ namespace Microsoft.Terminal.Remoting
Windows.Foundation.IReference WindowID;
}
+ [default_interface] runtimeclass QuitAllRequestedArgs
+ {
+ QuitAllRequestedArgs();
+ Windows.Foundation.IAsyncAction BeforeQuitAllAction;
+ }
+
struct PeasantInfo
{
UInt64 Id;
@@ -52,12 +58,13 @@ namespace Microsoft.Terminal.Remoting
void SummonAllWindows();
Boolean DoesQuakeWindowExist();
Windows.Foundation.Collections.IVectorView GetPeasantInfos { get; };
+ Windows.Foundation.Collections.IVector GetAllWindowLayouts();
event Windows.Foundation.TypedEventHandler