diff --git a/doc/cascadia/SettingsSchema.md b/doc/cascadia/SettingsSchema.md
index ffca902b73f..5bcb66826e8 100644
--- a/doc/cascadia/SettingsSchema.md
+++ b/doc/cascadia/SettingsSchema.md
@@ -129,6 +129,7 @@ For commands with arguments:
| `duplicateTab` | Make a copy and open the current tab. | | | |
| `find` | Open the search dialog box. | | | |
| `moveFocus` | Focus on a different pane depending on direction. | `direction`* | `left`, `right`, `up`, `down` | Direction in which the focus will move. |
+| `moveSelectionPoint` | Modify the existing selection by moving an endpoint. | `direction`* | `left`, `right`, `up`, `down` | Direction in which the focus will move. |
| `newTab` | Create a new tab. Without any arguments, this will open the default profile in a new tab. | 1. `commandLine`
2. `startingDirectory`
3. `tabTitle`
4. `index`
5. `profile` | 1. string
2. string
3. string
4. integer
5. string | 1. Executable run within the tab.
2. Directory in which the tab will open.
3. Title of the new tab.
4. Profile that will open based on its position in the dropdown (starting at 0).
5. Profile that will open based on its GUID or name. |
| `nextTab` | Open the tab to the right of the current one. | | | |
| `openNewTabDropdown` | Open the dropdown menu. | | | |
diff --git a/doc/cascadia/profiles.schema.json b/doc/cascadia/profiles.schema.json
index 2d84bb86f51..b2f51629969 100644
--- a/doc/cascadia/profiles.schema.json
+++ b/doc/cascadia/profiles.schema.json
@@ -62,6 +62,15 @@
],
"type": "string"
},
+ "SelectionExpansionMode": {
+ "enum": [
+ "cell",
+ "word",
+ "line",
+ "viewport",
+ "buffer"
+ ]
+ },
"Direction": {
"enum": [
"left",
@@ -233,6 +242,28 @@
}
]
},
+ "MoveSelectionPointAction": {
+ "description": "Arguments corresponding to a Move Selection Point Action",
+ "allOf": [
+ { "$ref": "#/definitions/ShortcutAction" },
+ {
+ "properties":
+ { "action": { "type": "string", "pattern": "moveSelectionPoint" },
+ "direction": {
+ "$ref": "#/definitions/Direction",
+ "default": "left",
+ "description": "The direction to move the selection endpoint in."
+ },
+ "expansionMode": {
+ "$ref": "#/definitions/SelectionExpansionMode",
+ "default": "cell",
+ "description": "The unit of expansion that the selection endpoint moves by."
+ }
+ }
+ }
+ ],
+ "required": [ "direction" ]
+ },
"OpenSettingsAction": {
"description": "Arguments corresponding to a Open Settings Action",
"allOf": [
@@ -287,6 +318,7 @@
{ "$ref": "#/definitions/NewTabAction" },
{ "$ref": "#/definitions/SwitchToTabAction" },
{ "$ref": "#/definitions/MoveFocusAction" },
+ { "$ref": "#/definitions/MoveSelectionPointAction" },
{ "$ref": "#/definitions/ResizePaneAction" },
{ "$ref": "#/definitions/SplitPaneAction" },
{ "$ref": "#/definitions/OpenSettingsAction" },
diff --git a/src/cascadia/LocalTests_TerminalApp/KeyBindingsTests.cpp b/src/cascadia/LocalTests_TerminalApp/KeyBindingsTests.cpp
index 760bfd94c8a..7a837d88378 100644
--- a/src/cascadia/LocalTests_TerminalApp/KeyBindingsTests.cpp
+++ b/src/cascadia/LocalTests_TerminalApp/KeyBindingsTests.cpp
@@ -344,7 +344,7 @@ namespace TerminalAppLocalTests
const auto& realArgs = actionAndArgs.Args().try_as();
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
- VERIFY_ARE_EQUAL(winrt::TerminalApp::SplitState::Automatic, realArgs.SplitStyle());
+ VERIFY_ARE_EQUAL(SplitState::Automatic, realArgs.SplitStyle());
}
{
KeyChord kc{ true, false, false, static_cast('D') };
@@ -353,7 +353,7 @@ namespace TerminalAppLocalTests
const auto& realArgs = actionAndArgs.Args().try_as();
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
- VERIFY_ARE_EQUAL(winrt::TerminalApp::SplitState::Vertical, realArgs.SplitStyle());
+ VERIFY_ARE_EQUAL(SplitState::Vertical, realArgs.SplitStyle());
}
{
KeyChord kc{ true, false, false, static_cast('E') };
@@ -362,7 +362,7 @@ namespace TerminalAppLocalTests
const auto& realArgs = actionAndArgs.Args().try_as();
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
- VERIFY_ARE_EQUAL(winrt::TerminalApp::SplitState::Horizontal, realArgs.SplitStyle());
+ VERIFY_ARE_EQUAL(SplitState::Horizontal, realArgs.SplitStyle());
}
{
KeyChord kc{ true, false, false, static_cast('F') };
@@ -371,7 +371,7 @@ namespace TerminalAppLocalTests
const auto& realArgs = actionAndArgs.Args().try_as();
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
- VERIFY_ARE_EQUAL(winrt::TerminalApp::SplitState::Automatic, realArgs.SplitStyle());
+ VERIFY_ARE_EQUAL(SplitState::Automatic, realArgs.SplitStyle());
}
{
KeyChord kc{ true, false, false, static_cast('G') };
@@ -380,7 +380,7 @@ namespace TerminalAppLocalTests
const auto& realArgs = actionAndArgs.Args().try_as();
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
- VERIFY_ARE_EQUAL(winrt::TerminalApp::SplitState::Automatic, realArgs.SplitStyle());
+ VERIFY_ARE_EQUAL(SplitState::Automatic, realArgs.SplitStyle());
}
{
KeyChord kc{ true, false, false, static_cast('H') };
@@ -389,7 +389,7 @@ namespace TerminalAppLocalTests
const auto& realArgs = actionAndArgs.Args().try_as();
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
- VERIFY_ARE_EQUAL(winrt::TerminalApp::SplitState::Automatic, realArgs.SplitStyle());
+ VERIFY_ARE_EQUAL(SplitState::Automatic, realArgs.SplitStyle());
}
{
KeyChord kc{ true, false, false, static_cast('I') };
@@ -398,7 +398,7 @@ namespace TerminalAppLocalTests
const auto& realArgs = actionAndArgs.Args().try_as();
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
- VERIFY_ARE_EQUAL(winrt::TerminalApp::SplitState::Automatic, realArgs.SplitStyle());
+ VERIFY_ARE_EQUAL(SplitState::Automatic, realArgs.SplitStyle());
}
}
diff --git a/src/cascadia/LocalTests_TerminalApp/SettingsTests.cpp b/src/cascadia/LocalTests_TerminalApp/SettingsTests.cpp
index 938ebd291df..ed3886f21d0 100644
--- a/src/cascadia/LocalTests_TerminalApp/SettingsTests.cpp
+++ b/src/cascadia/LocalTests_TerminalApp/SettingsTests.cpp
@@ -1773,7 +1773,7 @@ namespace TerminalAppLocalTests
const auto& realArgs = actionAndArgs.Args().try_as();
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
- VERIFY_ARE_EQUAL(winrt::TerminalApp::SplitState::Vertical, realArgs.SplitStyle());
+ VERIFY_ARE_EQUAL(SplitState::Vertical, realArgs.SplitStyle());
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
VERIFY_IS_TRUE(realArgs.TerminalArgs().Commandline().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().StartingDirectory().empty());
@@ -1792,7 +1792,7 @@ namespace TerminalAppLocalTests
const auto& realArgs = actionAndArgs.Args().try_as();
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
- VERIFY_ARE_EQUAL(winrt::TerminalApp::SplitState::Vertical, realArgs.SplitStyle());
+ VERIFY_ARE_EQUAL(SplitState::Vertical, realArgs.SplitStyle());
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
VERIFY_IS_TRUE(realArgs.TerminalArgs().Commandline().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().StartingDirectory().empty());
@@ -1812,7 +1812,7 @@ namespace TerminalAppLocalTests
const auto& realArgs = actionAndArgs.Args().try_as();
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
- VERIFY_ARE_EQUAL(winrt::TerminalApp::SplitState::Vertical, realArgs.SplitStyle());
+ VERIFY_ARE_EQUAL(SplitState::Vertical, realArgs.SplitStyle());
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
VERIFY_IS_TRUE(realArgs.TerminalArgs().Commandline().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().StartingDirectory().empty());
@@ -1832,7 +1832,7 @@ namespace TerminalAppLocalTests
const auto& realArgs = actionAndArgs.Args().try_as();
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
- VERIFY_ARE_EQUAL(winrt::TerminalApp::SplitState::Vertical, realArgs.SplitStyle());
+ VERIFY_ARE_EQUAL(SplitState::Vertical, realArgs.SplitStyle());
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
VERIFY_IS_TRUE(realArgs.TerminalArgs().Commandline().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().StartingDirectory().empty());
@@ -1852,7 +1852,7 @@ namespace TerminalAppLocalTests
const auto& realArgs = actionAndArgs.Args().try_as();
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
- VERIFY_ARE_EQUAL(winrt::TerminalApp::SplitState::Horizontal, realArgs.SplitStyle());
+ VERIFY_ARE_EQUAL(SplitState::Horizontal, realArgs.SplitStyle());
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
VERIFY_IS_FALSE(realArgs.TerminalArgs().Commandline().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().StartingDirectory().empty());
@@ -1872,7 +1872,7 @@ namespace TerminalAppLocalTests
const auto& realArgs = actionAndArgs.Args().try_as();
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
- VERIFY_ARE_EQUAL(winrt::TerminalApp::SplitState::Horizontal, realArgs.SplitStyle());
+ VERIFY_ARE_EQUAL(SplitState::Horizontal, realArgs.SplitStyle());
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
VERIFY_IS_FALSE(realArgs.TerminalArgs().Commandline().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().StartingDirectory().empty());
diff --git a/src/cascadia/TerminalApp/ActionAndArgs.cpp b/src/cascadia/TerminalApp/ActionAndArgs.cpp
index 9ba804b384d..52b655b3161 100644
--- a/src/cascadia/TerminalApp/ActionAndArgs.cpp
+++ b/src/cascadia/TerminalApp/ActionAndArgs.cpp
@@ -23,10 +23,11 @@ static constexpr std::string_view ScrolldownKey{ "scrollDown" };
static constexpr std::string_view ScrolluppageKey{ "scrollUpPage" };
static constexpr std::string_view ScrolldownpageKey{ "scrollDownPage" };
static constexpr std::string_view SwitchToTabKey{ "switchToTab" };
-static constexpr std::string_view OpenSettingsKey{ "openSettings" }; // TODO GH#2557: Add args for OpenSettings
+static constexpr std::string_view OpenSettingsKey{ "openSettings" };
static constexpr std::string_view SplitPaneKey{ "splitPane" };
static constexpr std::string_view ResizePaneKey{ "resizePane" };
static constexpr std::string_view MoveFocusKey{ "moveFocus" };
+static constexpr std::string_view MoveSelectionPointKey{ "moveSelectionPoint" };
static constexpr std::string_view FindKey{ "find" };
static constexpr std::string_view ToggleFullscreenKey{ "toggleFullscreen" };
static constexpr std::string_view SetTabColorKey{ "setTabColor" };
@@ -70,6 +71,7 @@ namespace winrt::TerminalApp::implementation
{ SwitchToTabKey, ShortcutAction::SwitchToTab },
{ ResizePaneKey, ShortcutAction::ResizePane },
{ MoveFocusKey, ShortcutAction::MoveFocus },
+ { MoveSelectionPointKey, ShortcutAction::MoveSelectionPoint },
{ OpenSettingsKey, ShortcutAction::OpenSettings },
{ ToggleFullscreenKey, ShortcutAction::ToggleFullscreen },
{ SplitPaneKey, ShortcutAction::SplitPane },
@@ -100,6 +102,8 @@ namespace winrt::TerminalApp::implementation
{ ShortcutAction::MoveFocus, winrt::TerminalApp::implementation::MoveFocusArgs::FromJson },
+ { ShortcutAction::MoveSelectionPoint, winrt::TerminalApp::implementation::MoveSelectionPointArgs::FromJson },
+
{ ShortcutAction::AdjustFontSize, winrt::TerminalApp::implementation::AdjustFontSizeArgs::FromJson },
{ ShortcutAction::SplitPane, winrt::TerminalApp::implementation::SplitPaneArgs::FromJson },
diff --git a/src/cascadia/TerminalApp/ActionArgs.cpp b/src/cascadia/TerminalApp/ActionArgs.cpp
index 012eacd7f22..9dae2bc7cae 100644
--- a/src/cascadia/TerminalApp/ActionArgs.cpp
+++ b/src/cascadia/TerminalApp/ActionArgs.cpp
@@ -13,6 +13,7 @@
#include "ResizePaneArgs.g.cpp"
#include "MoveFocusArgs.g.cpp"
#include "AdjustFontSizeArgs.g.cpp"
+#include "MoveSelectionPointArgs.g.cpp"
#include "SplitPaneArgs.g.cpp"
#include "OpenSettingsArgs.g.cpp"
#include "SetTabColorArgs.g.cpp"
@@ -20,6 +21,8 @@
#include
+using namespace winrt::Microsoft::Terminal::Settings;
+
namespace winrt::TerminalApp::implementation
{
winrt::hstring NewTerminalArgs::GenerateName() const
@@ -258,4 +261,9 @@ namespace winrt::TerminalApp::implementation
return RS_(L"ResetTabNameCommandKey");
}
+ winrt::hstring MoveSelectionPointArgs::GenerateName() const
+ {
+ // no generated name
+ return winrt::hstring();
+ }
}
diff --git a/src/cascadia/TerminalApp/ActionArgs.h b/src/cascadia/TerminalApp/ActionArgs.h
index eb233b5967a..8a08bf71afc 100644
--- a/src/cascadia/TerminalApp/ActionArgs.h
+++ b/src/cascadia/TerminalApp/ActionArgs.h
@@ -13,11 +13,13 @@
#include "ResizePaneArgs.g.h"
#include "MoveFocusArgs.g.h"
#include "AdjustFontSizeArgs.g.h"
+#include "MoveSelectionPointArgs.g.h"
#include "SplitPaneArgs.g.h"
#include "OpenSettingsArgs.g.h"
#include "SetTabColorArgs.g.h"
#include "RenameTabArgs.g.h"
+#include
#include "../../cascadia/inc/cppwinrt_utils.h"
#include "Utils.h"
#include "JsonUtils.h"
@@ -31,7 +33,7 @@
namespace winrt::TerminalApp::implementation
{
- using FromJsonResult = std::tuple>;
+ using FromJsonResult = std::tuple>;
struct ActionEventArgs : public ActionEventArgsT
{
@@ -69,7 +71,7 @@ namespace winrt::TerminalApp::implementation
other.ProfileIndex() == _ProfileIndex &&
other.Profile() == _Profile;
};
- static winrt::TerminalApp::NewTerminalArgs FromJson(const Json::Value& json)
+ static TerminalApp::NewTerminalArgs FromJson(const Json::Value& json)
{
// LOAD BEARING: Not using make_self here _will_ break you in the future!
auto args = winrt::make_self();
@@ -131,7 +133,7 @@ namespace winrt::TerminalApp::implementation
struct NewTabArgs : public NewTabArgsT
{
NewTabArgs() = default;
- GETSET_PROPERTY(winrt::TerminalApp::NewTerminalArgs, TerminalArgs, nullptr);
+ GETSET_PROPERTY(TerminalApp::NewTerminalArgs, TerminalArgs, nullptr);
public:
hstring GenerateName() const;
@@ -198,32 +200,32 @@ namespace winrt::TerminalApp::implementation
// - directionString: the string to attempt to parse
// Return Value:
// - The encoded Direction value, or Direction::None if it was an invalid string
- static TerminalApp::Direction ParseDirection(const std::string& directionString)
+ static Microsoft::Terminal::Settings::Direction ParseDirection(const std::string& directionString)
{
if (directionString == LeftString)
{
- return TerminalApp::Direction::Left;
+ return Microsoft::Terminal::Settings::Direction::Left;
}
else if (directionString == RightString)
{
- return TerminalApp::Direction::Right;
+ return Microsoft::Terminal::Settings::Direction::Right;
}
else if (directionString == UpString)
{
- return TerminalApp::Direction::Up;
+ return Microsoft::Terminal::Settings::Direction::Up;
}
else if (directionString == DownString)
{
- return TerminalApp::Direction::Down;
+ return Microsoft::Terminal::Settings::Direction::Down;
}
// default behavior for invalid data
- return TerminalApp::Direction::None;
+ return Microsoft::Terminal::Settings::Direction::None;
};
struct ResizePaneArgs : public ResizePaneArgsT
{
ResizePaneArgs() = default;
- GETSET_PROPERTY(TerminalApp::Direction, Direction, TerminalApp::Direction::None);
+ GETSET_PROPERTY(Microsoft::Terminal::Settings::Direction, Direction, Microsoft::Terminal::Settings::Direction::None);
static constexpr std::string_view DirectionKey{ "direction" };
@@ -247,7 +249,7 @@ namespace winrt::TerminalApp::implementation
{
args->_Direction = ParseDirection(directionString.asString());
}
- if (args->_Direction == TerminalApp::Direction::None)
+ if (args->_Direction == Microsoft::Terminal::Settings::Direction::None)
{
return { nullptr, { ::TerminalApp::SettingsLoadWarnings::MissingRequiredParameter } };
}
@@ -261,7 +263,7 @@ namespace winrt::TerminalApp::implementation
struct MoveFocusArgs : public MoveFocusArgsT
{
MoveFocusArgs() = default;
- GETSET_PROPERTY(TerminalApp::Direction, Direction, TerminalApp::Direction::None);
+ GETSET_PROPERTY(Microsoft::Terminal::Settings::Direction, Direction, Microsoft::Terminal::Settings::Direction::None);
static constexpr std::string_view DirectionKey{ "direction" };
@@ -285,7 +287,7 @@ namespace winrt::TerminalApp::implementation
{
args->_Direction = ParseDirection(directionString.asString());
}
- if (args->_Direction == TerminalApp::Direction::None)
+ if (args->_Direction == Microsoft::Terminal::Settings::Direction::None)
{
return { nullptr, { ::TerminalApp::SettingsLoadWarnings::MissingRequiredParameter } };
}
@@ -327,46 +329,126 @@ namespace winrt::TerminalApp::implementation
}
};
+ // Possible SelectionExpansionMode values
+ // TODO:GH#2550/#3475 - move these to a centralized deserializing place
+ static constexpr std::string_view CellString{ "cell" };
+ static constexpr std::string_view WordString{ "word" };
+ static constexpr std::string_view ViewportString{ "viewport" };
+ static constexpr std::string_view BufferString{ "buffer" };
+
+ // Function Description:
+ // - Helper function for parsing a SelectionExpansionMode from a string
+ // Arguments:
+ // - directionString: the string to attempt to parse
+ // Return Value:
+ // - The encoded SelectionExpansionMode value, or SelectionExpansionMode::Cell if it was an invalid string
+ static Microsoft::Terminal::Settings::SelectionExpansionMode ParseExpansionMode(const std::string& expansionModeString)
+ {
+ if (expansionModeString == CellString)
+ {
+ return Microsoft::Terminal::Settings::SelectionExpansionMode::Cell;
+ }
+ else if (expansionModeString == WordString)
+ {
+ return Microsoft::Terminal::Settings::SelectionExpansionMode::Word;
+ }
+ else if (expansionModeString == ViewportString)
+ {
+ return Microsoft::Terminal::Settings::SelectionExpansionMode::Viewport;
+ }
+ else if (expansionModeString == BufferString)
+ {
+ return Microsoft::Terminal::Settings::SelectionExpansionMode::Buffer;
+ }
+ // default behavior for invalid data
+ return Microsoft::Terminal::Settings::SelectionExpansionMode::Cell;
+ };
+
+ struct MoveSelectionPointArgs : public MoveSelectionPointArgsT
+ {
+ MoveSelectionPointArgs() = default;
+ GETSET_PROPERTY(Microsoft::Terminal::Settings::Direction, Direction, Microsoft::Terminal::Settings::Direction::None);
+ GETSET_PROPERTY(Microsoft::Terminal::Settings::SelectionExpansionMode, ExpansionMode, Microsoft::Terminal::Settings::SelectionExpansionMode::Cell);
+
+ static constexpr std::string_view DirectionKey{ "direction" };
+ static constexpr std::string_view ExpansionModeKey{ "expansionMode" };
+
+ public:
+ hstring GenerateName() const;
+
+ bool Equals(const IActionArgs& other)
+ {
+ auto otherAsUs = other.try_as();
+ if (otherAsUs)
+ {
+ return (otherAsUs->_Direction == _Direction) && (otherAsUs->_ExpansionMode == _ExpansionMode);
+ }
+ return false;
+ };
+ static FromJsonResult FromJson(const Json::Value& json)
+ {
+ // LOAD BEARING: Not using make_self here _will_ break you in the future!
+ auto args = winrt::make_self();
+ if (auto directionString{ json[JsonKey(DirectionKey)] })
+ {
+ args->_Direction = ParseDirection(directionString.asString());
+
+ if (auto expansionModeString{ json[JsonKey(ExpansionModeKey)] })
+ {
+ args->_ExpansionMode = ParseExpansionMode(expansionModeString.asString());
+ }
+ }
+ if (args->_Direction == Microsoft::Terminal::Settings::Direction::None)
+ {
+ return { nullptr, { ::TerminalApp::SettingsLoadWarnings::MissingRequiredParameter } };
+ }
+ else
+ {
+ return { *args, {} };
+ }
+ }
+ };
+
// Possible SplitState values
// TODO:GH#2550/#3475 - move these to a centralized deserializing place
static constexpr std::string_view VerticalKey{ "vertical" };
static constexpr std::string_view HorizontalKey{ "horizontal" };
static constexpr std::string_view AutomaticKey{ "auto" };
- static TerminalApp::SplitState ParseSplitState(const std::string& stateString)
+ static Microsoft::Terminal::Settings::SplitState ParseSplitState(const std::string& stateString)
{
if (stateString == VerticalKey)
{
- return TerminalApp::SplitState::Vertical;
+ return Microsoft::Terminal::Settings::SplitState::Vertical;
}
else if (stateString == HorizontalKey)
{
- return TerminalApp::SplitState::Horizontal;
+ return Microsoft::Terminal::Settings::SplitState::Horizontal;
}
else if (stateString == AutomaticKey)
{
- return TerminalApp::SplitState::Automatic;
+ return Microsoft::Terminal::Settings::SplitState::Automatic;
}
// default behavior for invalid data
- return TerminalApp::SplitState::Automatic;
+ return Microsoft::Terminal::Settings::SplitState::Automatic;
};
// Possible SplitType values
static constexpr std::string_view DuplicateKey{ "duplicate" };
- static TerminalApp::SplitType ParseSplitModeState(const std::string& stateString)
+ static Microsoft::Terminal::Settings::SplitType ParseSplitModeState(const std::string& stateString)
{
if (stateString == DuplicateKey)
{
- return TerminalApp::SplitType::Duplicate;
+ return Microsoft::Terminal::Settings::SplitType::Duplicate;
}
- return TerminalApp::SplitType::Manual;
+ return Microsoft::Terminal::Settings::SplitType::Manual;
}
struct SplitPaneArgs : public SplitPaneArgsT
{
SplitPaneArgs() = default;
- GETSET_PROPERTY(winrt::TerminalApp::SplitState, SplitStyle, winrt::TerminalApp::SplitState::Automatic);
- GETSET_PROPERTY(winrt::TerminalApp::NewTerminalArgs, TerminalArgs, nullptr);
- GETSET_PROPERTY(winrt::TerminalApp::SplitType, SplitMode, winrt::TerminalApp::SplitType::Manual);
+ GETSET_PROPERTY(Microsoft::Terminal::Settings::SplitState, SplitStyle, Microsoft::Terminal::Settings::SplitState::Automatic);
+ GETSET_PROPERTY(TerminalApp::NewTerminalArgs, TerminalArgs, nullptr);
+ GETSET_PROPERTY(Microsoft::Terminal::Settings::SplitType, SplitMode, Microsoft::Terminal::Settings::SplitType::Manual);
static constexpr std::string_view SplitKey{ "split" };
static constexpr std::string_view SplitModeKey{ "splitMode" };
@@ -415,28 +497,28 @@ namespace winrt::TerminalApp::implementation
// - targetString: the string to attempt to parse
// Return Value:
// - The encoded SettingsTarget value, or SettingsTarget::SettingsFile if it was an invalid string
- static TerminalApp::SettingsTarget ParseSettingsTarget(const std::string& targetString)
+ static Microsoft::Terminal::Settings::SettingsTarget ParseSettingsTarget(const std::string& targetString)
{
if (targetString == SettingsFileString)
{
- return TerminalApp::SettingsTarget::SettingsFile;
+ return Microsoft::Terminal::Settings::SettingsTarget::SettingsFile;
}
else if (targetString == DefaultsFileString)
{
- return TerminalApp::SettingsTarget::DefaultsFile;
+ return Microsoft::Terminal::Settings::SettingsTarget::DefaultsFile;
}
else if (targetString == AllFilesString)
{
- return TerminalApp::SettingsTarget::AllFiles;
+ return Microsoft::Terminal::Settings::SettingsTarget::AllFiles;
}
// default behavior for invalid data
- return TerminalApp::SettingsTarget::SettingsFile;
+ return Microsoft::Terminal::Settings::SettingsTarget::SettingsFile;
};
struct OpenSettingsArgs : public OpenSettingsArgsT
{
OpenSettingsArgs() = default;
- GETSET_PROPERTY(TerminalApp::SettingsTarget, Target, TerminalApp::SettingsTarget::SettingsFile);
+ GETSET_PROPERTY(Microsoft::Terminal::Settings::SettingsTarget, Target, Microsoft::Terminal::Settings::SettingsTarget::SettingsFile);
static constexpr std::string_view TargetKey{ "target" };
diff --git a/src/cascadia/TerminalApp/ActionArgs.idl b/src/cascadia/TerminalApp/ActionArgs.idl
index 36d5025bb4a..b1e20f89a3d 100644
--- a/src/cascadia/TerminalApp/ActionArgs.idl
+++ b/src/cascadia/TerminalApp/ActionArgs.idl
@@ -15,36 +15,6 @@ namespace TerminalApp
IActionArgs ActionArgs { get; };
};
- enum Direction
- {
- None = 0,
- Left,
- Right,
- Up,
- Down
- };
-
- enum SplitState
- {
- Automatic = -1,
- None = 0,
- Vertical = 1,
- Horizontal = 2
- };
-
- enum SplitType
- {
- Manual = 0,
- Duplicate = 1
- };
-
- enum SettingsTarget
- {
- SettingsFile = 0,
- DefaultsFile,
- AllFiles
- };
-
[default_interface] runtimeclass NewTerminalArgs {
NewTerminalArgs();
String Commandline;
@@ -81,12 +51,12 @@ namespace TerminalApp
[default_interface] runtimeclass ResizePaneArgs : IActionArgs
{
- Direction Direction { get; };
+ Microsoft.Terminal.Settings.Direction Direction { get; };
};
[default_interface] runtimeclass MoveFocusArgs : IActionArgs
{
- Direction Direction { get; };
+ Microsoft.Terminal.Settings.Direction Direction { get; };
};
[default_interface] runtimeclass AdjustFontSizeArgs : IActionArgs
@@ -94,16 +64,22 @@ namespace TerminalApp
Int32 Delta { get; };
};
+ [default_interface] runtimeclass MoveSelectionPointArgs : IActionArgs
+ {
+ Microsoft.Terminal.Settings.Direction Direction { get; };
+ Microsoft.Terminal.Settings.SelectionExpansionMode ExpansionMode { get; };
+ };
+
[default_interface] runtimeclass SplitPaneArgs : IActionArgs
{
- SplitState SplitStyle { get; };
+ Microsoft.Terminal.Settings.SplitState SplitStyle { get; };
NewTerminalArgs TerminalArgs { get; };
- SplitType SplitMode { get; };
+ Microsoft.Terminal.Settings.SplitType SplitMode { get; };
};
[default_interface] runtimeclass OpenSettingsArgs : IActionArgs
{
- SettingsTarget Target { get; };
+ Microsoft.Terminal.Settings.SettingsTarget Target { get; };
};
[default_interface] runtimeclass SetTabColorArgs : IActionArgs
diff --git a/src/cascadia/TerminalApp/AppActionHandlers.cpp b/src/cascadia/TerminalApp/AppActionHandlers.cpp
index e972002a8a3..6cbbbfb3c5a 100644
--- a/src/cascadia/TerminalApp/AppActionHandlers.cpp
+++ b/src/cascadia/TerminalApp/AppActionHandlers.cpp
@@ -164,7 +164,7 @@ namespace winrt::TerminalApp::implementation
{
if (const auto& realArgs = args.ActionArgs().try_as())
{
- if (realArgs.Direction() == TerminalApp::Direction::None)
+ if (realArgs.Direction() == Settings::Direction::None)
{
// Do nothing
args.Handled(false);
@@ -182,7 +182,7 @@ namespace winrt::TerminalApp::implementation
{
if (const auto& realArgs = args.ActionArgs().try_as())
{
- if (realArgs.Direction() == TerminalApp::Direction::None)
+ if (realArgs.Direction() == Settings::Direction::None)
{
// Do nothing
args.Handled(false);
@@ -312,4 +312,15 @@ namespace winrt::TerminalApp::implementation
}
args.Handled(true);
}
+
+ void TerminalPage::_HandleMoveSelectionPoint(const IInspectable& /*sender*/,
+ const TerminalApp::ActionEventArgs& args)
+ {
+ if (const auto& realArgs = args.ActionArgs().try_as())
+ {
+ const auto termControl = _GetActiveControl();
+ const auto handled = termControl.MoveSelectionPoint(realArgs.Direction(), realArgs.ExpansionMode());
+ args.Handled(handled);
+ }
+ }
}
diff --git a/src/cascadia/TerminalApp/AppCommandlineArgs.cpp b/src/cascadia/TerminalApp/AppCommandlineArgs.cpp
index 769be092157..842d28fe954 100644
--- a/src/cascadia/TerminalApp/AppCommandlineArgs.cpp
+++ b/src/cascadia/TerminalApp/AppCommandlineArgs.cpp
@@ -8,6 +8,7 @@
#include
using namespace winrt::TerminalApp;
+using namespace winrt::Microsoft::Terminal::Settings;
using namespace TerminalApp;
// Either a ; at the start of a line, or a ; preceded by any non-\ char.
diff --git a/src/cascadia/TerminalApp/Pane.cpp b/src/cascadia/TerminalApp/Pane.cpp
index b931755c1e3..970de7fbecc 100644
--- a/src/cascadia/TerminalApp/Pane.cpp
+++ b/src/cascadia/TerminalApp/Pane.cpp
@@ -1538,8 +1538,8 @@ int Pane::GetLeafPaneCount() const noexcept
// - nullopt if `target` is not this pane or a child of this pane, otherwise the
// SplitState that `target` would use for an `Automatic` split given
// `availableSpace`
-std::optional Pane::PreCalculateAutoSplit(const std::shared_ptr target,
- const winrt::Windows::Foundation::Size availableSpace) const
+std::optional Pane::PreCalculateAutoSplit(const std::shared_ptr target,
+ const winrt::Windows::Foundation::Size availableSpace) const
{
if (_IsLeaf())
{
diff --git a/src/cascadia/TerminalApp/Pane.h b/src/cascadia/TerminalApp/Pane.h
index 7041db1f0cb..830bb4a3a49 100644
--- a/src/cascadia/TerminalApp/Pane.h
+++ b/src/cascadia/TerminalApp/Pane.h
@@ -55,15 +55,15 @@ class Pane : public std::enable_shared_from_this
const GUID& profile);
void ResizeContent(const winrt::Windows::Foundation::Size& newSize);
void Relayout();
- bool ResizePane(const winrt::TerminalApp::Direction& direction);
- bool NavigateFocus(const winrt::TerminalApp::Direction& direction);
+ bool ResizePane(const winrt::Microsoft::Terminal::Settings::Direction& direction);
+ bool NavigateFocus(const winrt::Microsoft::Terminal::Settings::Direction& direction);
- bool CanSplit(winrt::TerminalApp::SplitState splitType);
- std::pair, std::shared_ptr> Split(winrt::TerminalApp::SplitState splitType,
+ bool CanSplit(winrt::Microsoft::Terminal::Settings::SplitState splitType);
+ std::pair, std::shared_ptr> Split(winrt::Microsoft::Terminal::Settings::SplitState splitType,
const GUID& profile,
const winrt::Microsoft::Terminal::TerminalControl::TermControl& control);
float CalcSnappedDimension(const bool widthOrHeight, const float dimension) const;
- std::optional PreCalculateAutoSplit(const std::shared_ptr target, const winrt::Windows::Foundation::Size parentSize) const;
+ std::optional PreCalculateAutoSplit(const std::shared_ptr target, const winrt::Windows::Foundation::Size parentSize) const;
void Shutdown();
void Close();
@@ -86,7 +86,7 @@ class Pane : public std::enable_shared_from_this
std::shared_ptr _firstChild{ nullptr };
std::shared_ptr _secondChild{ nullptr };
- winrt::TerminalApp::SplitState _splitState{ winrt::TerminalApp::SplitState::None };
+ winrt::Microsoft::Terminal::Settings::SplitState _splitState{ winrt::Microsoft::Terminal::Settings::SplitState::None };
float _desiredSplitPosition;
bool _lastActive{ false };
@@ -105,8 +105,8 @@ class Pane : public std::enable_shared_from_this
bool _HasFocusedChild() const noexcept;
void _SetupChildCloseHandlers();
- bool _CanSplit(winrt::TerminalApp::SplitState splitType);
- std::pair, std::shared_ptr> _Split(winrt::TerminalApp::SplitState splitType,
+ bool _CanSplit(winrt::Microsoft::Terminal::Settings::SplitState splitType);
+ std::pair, std::shared_ptr> _Split(winrt::Microsoft::Terminal::Settings::SplitState splitType,
const GUID& profile,
const winrt::Microsoft::Terminal::TerminalControl::TermControl& control);
@@ -114,8 +114,8 @@ class Pane : public std::enable_shared_from_this
void _ApplySplitDefinitions();
void _UpdateBorders();
- bool _Resize(const winrt::TerminalApp::Direction& direction);
- bool _NavigateFocus(const winrt::TerminalApp::Direction& direction);
+ bool _Resize(const winrt::Microsoft::Terminal::Settings::Direction& direction);
+ bool _NavigateFocus(const winrt::Microsoft::Terminal::Settings::Direction& direction);
void _CloseChild(const bool closeFirst);
winrt::fire_and_forget _CloseChildRoutine(const bool closeFirst);
@@ -134,9 +134,9 @@ class Pane : public std::enable_shared_from_this
LayoutSizeNode _CreateMinSizeTree(const bool widthOrHeight) const;
float _ClampSplitPosition(const bool widthOrHeight, const float requestedValue, const float totalSize) const;
- winrt::TerminalApp::SplitState _convertAutomaticSplitState(const winrt::TerminalApp::SplitState& splitType) const;
+ winrt::Microsoft::Terminal::Settings::SplitState _convertAutomaticSplitState(const winrt::Microsoft::Terminal::Settings::SplitState& splitType) const;
- std::optional _preCalculateAutoSplit(const std::shared_ptr target, const winrt::Windows::Foundation::Size parentSize) const;
+ std::optional _preCalculateAutoSplit(const std::shared_ptr target, const winrt::Windows::Foundation::Size parentSize) const;
// Function Description:
// - Returns true if the given direction can be used with the given split
@@ -151,23 +151,23 @@ class Pane : public std::enable_shared_from_this
// - splitType: The winrt::TerminalApp::SplitState to compare
// Return Value:
// - true iff the direction is perpendicular to the splitType. False for
- // winrt::TerminalApp::SplitState::None.
- static constexpr bool DirectionMatchesSplit(const winrt::TerminalApp::Direction& direction,
- const winrt::TerminalApp::SplitState& splitType)
+ // SplitState::None.
+ static constexpr bool DirectionMatchesSplit(const winrt::Microsoft::Terminal::Settings::Direction& direction,
+ const winrt::Microsoft::Terminal::Settings::SplitState& splitType)
{
- if (splitType == winrt::TerminalApp::SplitState::None)
+ if (splitType == winrt::Microsoft::Terminal::Settings::SplitState::None)
{
return false;
}
- else if (splitType == winrt::TerminalApp::SplitState::Horizontal)
+ else if (splitType == winrt::Microsoft::Terminal::Settings::SplitState::Horizontal)
{
- return direction == winrt::TerminalApp::Direction::Up ||
- direction == winrt::TerminalApp::Direction::Down;
+ return direction == winrt::Microsoft::Terminal::Settings::Direction::Up ||
+ direction == winrt::Microsoft::Terminal::Settings::Direction::Down;
}
- else if (splitType == winrt::TerminalApp::SplitState::Vertical)
+ else if (splitType == winrt::Microsoft::Terminal::Settings::SplitState::Vertical)
{
- return direction == winrt::TerminalApp::Direction::Left ||
- direction == winrt::TerminalApp::Direction::Right;
+ return direction == winrt::Microsoft::Terminal::Settings::Direction::Left ||
+ direction == winrt::Microsoft::Terminal::Settings::Direction::Right;
}
return false;
}
diff --git a/src/cascadia/TerminalApp/ShortcutActionDispatch.cpp b/src/cascadia/TerminalApp/ShortcutActionDispatch.cpp
index f36654dd0ce..a13abfed617 100644
--- a/src/cascadia/TerminalApp/ShortcutActionDispatch.cpp
+++ b/src/cascadia/TerminalApp/ShortcutActionDispatch.cpp
@@ -139,6 +139,12 @@ namespace winrt::TerminalApp::implementation
break;
}
+ case ShortcutAction::MoveSelectionPoint:
+ {
+ _MoveSelectionPointHandlers(*this, *eventArgs);
+ break;
+ }
+
case ShortcutAction::AdjustFontSize:
{
_AdjustFontSizeHandlers(*this, *eventArgs);
diff --git a/src/cascadia/TerminalApp/ShortcutActionDispatch.h b/src/cascadia/TerminalApp/ShortcutActionDispatch.h
index 5a70f2abd10..e95c0c99cad 100644
--- a/src/cascadia/TerminalApp/ShortcutActionDispatch.h
+++ b/src/cascadia/TerminalApp/ShortcutActionDispatch.h
@@ -46,6 +46,7 @@ namespace winrt::TerminalApp::implementation
TYPED_EVENT(ResizePane, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs);
TYPED_EVENT(Find, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs);
TYPED_EVENT(MoveFocus, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs);
+ TYPED_EVENT(MoveSelectionPoint, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs);
TYPED_EVENT(ToggleFullscreen, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs);
TYPED_EVENT(ToggleCommandPalette, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs);
TYPED_EVENT(SetTabColor, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs);
diff --git a/src/cascadia/TerminalApp/ShortcutActionDispatch.idl b/src/cascadia/TerminalApp/ShortcutActionDispatch.idl
index 89d4aabbfe9..96d7b3b185a 100644
--- a/src/cascadia/TerminalApp/ShortcutActionDispatch.idl
+++ b/src/cascadia/TerminalApp/ShortcutActionDispatch.idl
@@ -30,6 +30,7 @@ namespace TerminalApp
ScrollDownPage,
ResizePane,
MoveFocus,
+ MoveSelectionPoint,
Find,
ToggleFullscreen,
SetTabColor,
diff --git a/src/cascadia/TerminalApp/Tab.cpp b/src/cascadia/TerminalApp/Tab.cpp
index 0e9838ec69c..3f40598db73 100644
--- a/src/cascadia/TerminalApp/Tab.cpp
+++ b/src/cascadia/TerminalApp/Tab.cpp
@@ -286,7 +286,7 @@ namespace winrt::TerminalApp::implementation
// - splitType: The type of split we want to create.
// Return Value:
// - True if the focused pane can be split. False otherwise.
- bool Tab::CanSplitPane(winrt::TerminalApp::SplitState splitType)
+ bool Tab::CanSplitPane(SplitState splitType)
{
return _activePane->CanSplit(splitType);
}
@@ -300,7 +300,7 @@ namespace winrt::TerminalApp::implementation
// - control: A TermControl to use in the new pane.
// Return Value:
// -
- void Tab::SplitPane(winrt::TerminalApp::SplitState splitType, const GUID& profile, TermControl& control)
+ void Tab::SplitPane(SplitState splitType, const GUID& profile, TermControl& control)
{
auto [first, second] = _activePane->Split(splitType, profile, control);
_activePane = first;
@@ -346,7 +346,7 @@ namespace winrt::TerminalApp::implementation
// - direction: The direction to move the separator in.
// Return Value:
// -
- void Tab::ResizePane(const winrt::TerminalApp::Direction& direction)
+ void Tab::ResizePane(const Direction& direction)
{
// NOTE: This _must_ be called on the root pane, so that it can propagate
// throughout the entire tree.
@@ -360,7 +360,7 @@ namespace winrt::TerminalApp::implementation
// - direction: The direction to move the focus in.
// Return Value:
// -
- void Tab::NavigateFocus(const winrt::TerminalApp::Direction& direction)
+ void Tab::NavigateFocus(const Direction& direction)
{
// NOTE: This _must_ be called on the root pane, so that it can propagate
// throughout the entire tree.
diff --git a/src/cascadia/TerminalApp/Tab.h b/src/cascadia/TerminalApp/Tab.h
index be76c1b7912..314fa279c41 100644
--- a/src/cascadia/TerminalApp/Tab.h
+++ b/src/cascadia/TerminalApp/Tab.h
@@ -18,14 +18,14 @@ namespace winrt::TerminalApp::implementation
{
public:
Tab() = delete;
- Tab(const GUID& profile, const winrt::Microsoft::Terminal::TerminalControl::TermControl& control);
+ Tab(const GUID& profile, const Microsoft::Terminal::TerminalControl::TermControl& control);
// Called after construction to perform the necessary setup, which relies on weak_ptr
- void Initialize(const winrt::Microsoft::Terminal::TerminalControl::TermControl& control);
+ void Initialize(const Microsoft::Terminal::TerminalControl::TermControl& control);
- winrt::Microsoft::UI::Xaml::Controls::TabViewItem GetTabViewItem();
- winrt::Windows::UI::Xaml::UIElement GetRootElement();
- winrt::Microsoft::Terminal::TerminalControl::TermControl GetActiveTerminalControl() const;
+ Microsoft::UI::Xaml::Controls::TabViewItem GetTabViewItem();
+ Windows::UI::Xaml::UIElement GetRootElement();
+ Microsoft::Terminal::TerminalControl::TermControl GetActiveTerminalControl() const;
std::optional GetFocusedProfile() const noexcept;
bool IsFocused() const noexcept;
@@ -33,19 +33,19 @@ namespace winrt::TerminalApp::implementation
winrt::fire_and_forget Scroll(const int delta);
- bool CanSplitPane(winrt::TerminalApp::SplitState splitType);
- void SplitPane(winrt::TerminalApp::SplitState splitType, const GUID& profile, winrt::Microsoft::Terminal::TerminalControl::TermControl& control);
+ bool CanSplitPane(Microsoft::Terminal::Settings::SplitState splitType);
+ void SplitPane(Microsoft::Terminal::Settings::SplitState splitType, const GUID& profile, Microsoft::Terminal::TerminalControl::TermControl& control);
winrt::fire_and_forget UpdateIcon(const winrt::hstring iconPath);
float CalcSnappedDimension(const bool widthOrHeight, const float dimension) const;
- SplitState PreCalculateAutoSplit(winrt::Windows::Foundation::Size rootSize) const;
+ Microsoft::Terminal::Settings::SplitState PreCalculateAutoSplit(Windows::Foundation::Size rootSize) const;
- void ResizeContent(const winrt::Windows::Foundation::Size& newSize);
- void ResizePane(const winrt::TerminalApp::Direction& direction);
- void NavigateFocus(const winrt::TerminalApp::Direction& direction);
+ void ResizeContent(const Windows::Foundation::Size& newSize);
+ void ResizePane(const Microsoft::Terminal::Settings::Direction& direction);
+ void NavigateFocus(const Microsoft::Terminal::Settings::Direction& direction);
- void UpdateSettings(const winrt::Microsoft::Terminal::Settings::TerminalSettings& settings, const GUID& profile);
+ void UpdateSettings(const Microsoft::Terminal::Settings::TerminalSettings& settings, const GUID& profile);
winrt::hstring GetActiveTitle() const;
void Shutdown();
@@ -63,7 +63,7 @@ namespace winrt::TerminalApp::implementation
WINRT_CALLBACK(Closed, winrt::Windows::Foundation::EventHandler);
WINRT_CALLBACK(PropertyChanged, Windows::UI::Xaml::Data::PropertyChangedEventHandler);
DECLARE_EVENT(ActivePaneChanged, _ActivePaneChangedHandlers, winrt::delegate<>);
- DECLARE_EVENT(ColorSelected, _colorSelected, winrt::delegate);
+ DECLARE_EVENT(ColorSelected, _colorSelected, winrt::delegate);
DECLARE_EVENT(ColorCleared, _colorCleared, winrt::delegate<>);
OBSERVABLE_GETSET_PROPERTY(winrt::hstring, Title, _PropertyChangedHandlers);
@@ -73,11 +73,11 @@ namespace winrt::TerminalApp::implementation
std::shared_ptr _rootPane{ nullptr };
std::shared_ptr _activePane{ nullptr };
winrt::hstring _lastIconPath{};
- winrt::TerminalApp::ColorPickupFlyout _tabColorPickup{};
- std::optional _tabColor{};
+ TerminalApp::ColorPickupFlyout _tabColorPickup{};
+ std::optional _tabColor{};
bool _focused{ false };
- winrt::Microsoft::UI::Xaml::Controls::TabViewItem _tabViewItem{ nullptr };
+ Microsoft::UI::Xaml::Controls::TabViewItem _tabViewItem{ nullptr };
winrt::hstring _runtimeTabText{};
bool _inRename{ false };
@@ -89,9 +89,9 @@ namespace winrt::TerminalApp::implementation
void _CreateContextMenu();
void _RefreshVisualState();
- void _BindEventHandlers(const winrt::Microsoft::Terminal::TerminalControl::TermControl& control) noexcept;
+ void _BindEventHandlers(const Microsoft::Terminal::TerminalControl::TermControl& control) noexcept;
- void _AttachEventHandlersToControl(const winrt::Microsoft::Terminal::TerminalControl::TermControl& control);
+ void _AttachEventHandlersToControl(const Microsoft::Terminal::TerminalControl::TermControl& control);
void _AttachEventHandlersToPane(std::shared_ptr pane);
int _GetLeafPaneCount() const noexcept;
diff --git a/src/cascadia/TerminalApp/TerminalPage.cpp b/src/cascadia/TerminalApp/TerminalPage.cpp
index 47bc5100e6b..74b5476d821 100644
--- a/src/cascadia/TerminalApp/TerminalPage.cpp
+++ b/src/cascadia/TerminalApp/TerminalPage.cpp
@@ -408,8 +408,8 @@ namespace winrt::TerminalApp::implementation
if (altPressed && !debugTap)
{
- page->_SplitPane(TerminalApp::SplitState::Automatic,
- TerminalApp::SplitType::Manual,
+ page->_SplitPane(SplitState::Automatic,
+ SplitType::Manual,
*newTerminalArgs);
}
else
@@ -644,7 +644,7 @@ namespace winrt::TerminalApp::implementation
// Return value:
// - the desired connection
TerminalConnection::ITerminalConnection TerminalPage::_CreateConnectionFromSettings(GUID profileGuid,
- winrt::Microsoft::Terminal::Settings::TerminalSettings settings)
+ TerminalSettings settings)
{
const auto* const profile = _settings->FindProfile(profileGuid);
@@ -798,6 +798,7 @@ namespace winrt::TerminalApp::implementation
_actionDispatch->SwitchToTab({ this, &TerminalPage::_HandleSwitchToTab });
_actionDispatch->ResizePane({ this, &TerminalPage::_HandleResizePane });
_actionDispatch->MoveFocus({ this, &TerminalPage::_HandleMoveFocus });
+ _actionDispatch->MoveSelectionPoint({ this, &TerminalPage::_HandleMoveSelectionPoint });
_actionDispatch->CopyText({ this, &TerminalPage::_HandleCopyText });
_actionDispatch->AdjustFontSize({ this, &TerminalPage::_HandleAdjustFontSize });
_actionDispatch->Find({ this, &TerminalPage::_HandleFind });
@@ -1260,12 +1261,12 @@ namespace winrt::TerminalApp::implementation
// - newTerminalArgs: An object that may contain a blob of parameters to
// control which profile is created and with possible other
// configurations. See CascadiaSettings::BuildSettings for more details.
- void TerminalPage::_SplitPane(const TerminalApp::SplitState splitType,
- const TerminalApp::SplitType splitMode,
+ void TerminalPage::_SplitPane(const SplitState splitType,
+ const SplitType splitMode,
const winrt::TerminalApp::NewTerminalArgs& newTerminalArgs)
{
// Do nothing if we're requesting no split.
- if (splitType == TerminalApp::SplitState::None)
+ if (splitType == SplitState::None)
{
return;
}
@@ -1285,7 +1286,7 @@ namespace winrt::TerminalApp::implementation
GUID realGuid;
bool profileFound = false;
- if (splitMode == TerminalApp::SplitType::Duplicate)
+ if (splitMode == SplitType::Duplicate)
{
std::optional current_guid = focusedTab->GetFocusedProfile();
if (current_guid)
@@ -1414,21 +1415,21 @@ namespace winrt::TerminalApp::implementation
// Return Value:
// - a string representation of the key modifiers for the shortcut
//NOTE: This needs to be localized with https://github.com/microsoft/terminal/issues/794 if XAML framework issue not resolved before then
- static std::wstring _FormatOverrideShortcutText(Settings::KeyModifiers modifiers)
+ static std::wstring _FormatOverrideShortcutText(KeyModifiers modifiers)
{
std::wstring buffer{ L"" };
- if (WI_IsFlagSet(modifiers, Settings::KeyModifiers::Ctrl))
+ if (WI_IsFlagSet(modifiers, KeyModifiers::Ctrl))
{
buffer += L"Ctrl+";
}
- if (WI_IsFlagSet(modifiers, Settings::KeyModifiers::Shift))
+ if (WI_IsFlagSet(modifiers, KeyModifiers::Shift))
{
buffer += L"Shift+";
}
- if (WI_IsFlagSet(modifiers, Settings::KeyModifiers::Alt))
+ if (WI_IsFlagSet(modifiers, KeyModifiers::Alt))
{
buffer += L"Alt+";
}
@@ -1442,7 +1443,7 @@ namespace winrt::TerminalApp::implementation
// Arguments:
// - MenuFlyoutItem that will be displayed, and a KeyChord to map an accelerator
void TerminalPage::_SetAcceleratorForMenuItem(WUX::Controls::MenuFlyoutItem& menuItem,
- const winrt::Microsoft::Terminal::Settings::KeyChord& keyChord)
+ const KeyChord& keyChord)
{
#ifdef DEP_MICROSOFT_UI_XAML_708_FIXED
// work around https://github.com/microsoft/microsoft-ui-xaml/issues/708 in case of VK_OEM_COMMA
diff --git a/src/cascadia/TerminalApp/TerminalPage.h b/src/cascadia/TerminalApp/TerminalPage.h
index ec692558dd1..789766a57c9 100644
--- a/src/cascadia/TerminalApp/TerminalPage.h
+++ b/src/cascadia/TerminalApp/TerminalPage.h
@@ -54,12 +54,12 @@ namespace winrt::TerminalApp::implementation
void SetStartupActions(std::deque& actions);
// -------------------------------- WinRT Events ---------------------------------
- DECLARE_EVENT_WITH_TYPED_EVENT_HANDLER(TitleChanged, _titleChangeHandlers, winrt::Windows::Foundation::IInspectable, winrt::hstring);
- DECLARE_EVENT_WITH_TYPED_EVENT_HANDLER(LastTabClosed, _lastTabClosedHandlers, winrt::Windows::Foundation::IInspectable, winrt::TerminalApp::LastTabClosedEventArgs);
- DECLARE_EVENT_WITH_TYPED_EVENT_HANDLER(SetTitleBarContent, _setTitleBarContentHandlers, winrt::Windows::Foundation::IInspectable, winrt::Windows::UI::Xaml::UIElement);
- DECLARE_EVENT_WITH_TYPED_EVENT_HANDLER(ShowDialog, _showDialogHandlers, winrt::Windows::Foundation::IInspectable, winrt::Windows::UI::Xaml::Controls::ContentDialog);
- DECLARE_EVENT_WITH_TYPED_EVENT_HANDLER(ToggleFullscreen, _toggleFullscreenHandlers, winrt::Windows::Foundation::IInspectable, winrt::TerminalApp::ToggleFullscreenEventArgs);
- TYPED_EVENT(Initialized, winrt::Windows::Foundation::IInspectable, winrt::Windows::UI::Xaml::RoutedEventArgs);
+ DECLARE_EVENT_WITH_TYPED_EVENT_HANDLER(TitleChanged, _titleChangeHandlers, Windows::Foundation::IInspectable, winrt::hstring);
+ DECLARE_EVENT_WITH_TYPED_EVENT_HANDLER(LastTabClosed, _lastTabClosedHandlers, Windows::Foundation::IInspectable, TerminalApp::LastTabClosedEventArgs);
+ DECLARE_EVENT_WITH_TYPED_EVENT_HANDLER(SetTitleBarContent, _setTitleBarContentHandlers, Windows::Foundation::IInspectable, Windows::UI::Xaml::UIElement);
+ DECLARE_EVENT_WITH_TYPED_EVENT_HANDLER(ShowDialog, _showDialogHandlers, Windows::Foundation::IInspectable, Windows::UI::Xaml::Controls::ContentDialog);
+ DECLARE_EVENT_WITH_TYPED_EVENT_HANDLER(ToggleFullscreen, _toggleFullscreenHandlers, Windows::Foundation::IInspectable, TerminalApp::ToggleFullscreenEventArgs);
+ TYPED_EVENT(Initialized, Windows::Foundation::IInspectable, Windows::UI::Xaml::RoutedEventArgs);
private:
friend struct TerminalPageT; // for Xaml to bind events
@@ -79,7 +79,7 @@ namespace winrt::TerminalApp::implementation
Windows::Foundation::Collections::IObservableVector _tabs;
winrt::com_ptr _GetStrongTabImpl(const uint32_t index) const;
- winrt::com_ptr _GetStrongTabImpl(const ::winrt::TerminalApp::Tab& tab) const;
+ winrt::com_ptr _GetStrongTabImpl(const TerminalApp::Tab& tab) const;
bool _isFullscreen{ false };
@@ -89,7 +89,7 @@ namespace winrt::TerminalApp::implementation
winrt::com_ptr _actionDispatch{ winrt::make_self() };
- winrt::Windows::UI::Xaml::Controls::Grid::LayoutUpdated_revoker _layoutUpdatedRevoker;
+ Windows::UI::Xaml::Controls::Grid::LayoutUpdated_revoker _layoutUpdatedRevoker;
StartupState _startupState{ StartupState::NotInitialized };
std::deque _startupActions;
@@ -100,9 +100,9 @@ namespace winrt::TerminalApp::implementation
void _CreateNewTabFlyout();
void _OpenNewTabDropdown();
- void _OpenNewTab(const winrt::TerminalApp::NewTerminalArgs& newTerminalArgs);
- void _CreateNewTabFromSettings(GUID profileGuid, winrt::Microsoft::Terminal::Settings::TerminalSettings settings);
- winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection _CreateConnectionFromSettings(GUID profileGuid, winrt::Microsoft::Terminal::Settings::TerminalSettings settings);
+ void _OpenNewTab(const TerminalApp::NewTerminalArgs& newTerminalArgs);
+ void _CreateNewTabFromSettings(GUID profileGuid, Microsoft::Terminal::Settings::TerminalSettings settings);
+ Microsoft::Terminal::TerminalConnection::ITerminalConnection _CreateConnectionFromSettings(GUID profileGuid, Microsoft::Terminal::Settings::TerminalSettings settings);
void _SettingsButtonOnClick(const IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& eventArgs);
void _FeedbackButtonOnClick(const IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& eventArgs);
@@ -125,9 +125,9 @@ namespace winrt::TerminalApp::implementation
void _SelectNextTab(const bool bMoveRight);
bool _SelectTab(const uint32_t tabIndex);
- void _MoveFocus(const Direction& direction);
+ void _MoveFocus(const Microsoft::Terminal::Settings::Direction& direction);
- winrt::Microsoft::Terminal::TerminalControl::TermControl _GetActiveControl();
+ Microsoft::Terminal::TerminalControl::TermControl _GetActiveControl();
std::optional _GetFocusedTabIndex() const noexcept;
winrt::com_ptr _GetFocusedTab();
winrt::fire_and_forget _SetFocusedTabIndex(const uint32_t tabIndex);
@@ -140,19 +140,19 @@ namespace winrt::TerminalApp::implementation
// Todo: add more event implementations here
// MSFT:20641986: Add keybindings for New Window
void _Scroll(int delta);
- void _SplitPane(const winrt::TerminalApp::SplitState splitType, const winrt::TerminalApp::SplitType splitMode = winrt::TerminalApp::SplitType::Manual, const winrt::TerminalApp::NewTerminalArgs& newTerminalArgs = nullptr);
- void _ResizePane(const Direction& direction);
+ void _SplitPane(const Microsoft::Terminal::Settings::SplitState splitType, const Microsoft::Terminal::Settings::SplitType splitMode = winrt::Microsoft::Terminal::Settings::SplitType::Manual, const winrt::TerminalApp::NewTerminalArgs& newTerminalArgs = nullptr);
+ void _ResizePane(const Microsoft::Terminal::Settings::Direction& direction);
void _ScrollPage(int delta);
void _SetAcceleratorForMenuItem(Windows::UI::Xaml::Controls::MenuFlyoutItem& menuItem, const winrt::Microsoft::Terminal::Settings::KeyChord& keyChord);
- winrt::fire_and_forget _CopyToClipboardHandler(const IInspectable sender, const winrt::Microsoft::Terminal::TerminalControl::CopyToClipboardEventArgs copiedData);
+ winrt::fire_and_forget _CopyToClipboardHandler(const IInspectable sender, const Microsoft::Terminal::TerminalControl::CopyToClipboardEventArgs copiedData);
winrt::fire_and_forget _PasteFromClipboardHandler(const IInspectable sender,
const Microsoft::Terminal::TerminalControl::PasteFromClipboardEventArgs eventArgs);
bool _CopyText(const bool trimTrailingWhitespace);
void _PasteText();
- static fire_and_forget PasteFromClipboard(winrt::Microsoft::Terminal::TerminalControl::PasteFromClipboardEventArgs eventArgs);
+ static fire_and_forget PasteFromClipboard(Microsoft::Terminal::TerminalControl::PasteFromClipboardEventArgs eventArgs);
- fire_and_forget _LaunchSettings(const winrt::TerminalApp::SettingsTarget target);
+ fire_and_forget _LaunchSettings(const Microsoft::Terminal::Settings::SettingsTarget target);
void _OnTabClick(const IInspectable& sender, const Windows::UI::Xaml::Input::PointerRoutedEventArgs& eventArgs);
void _OnTabSelectionChanged(const IInspectable& sender, const Windows::UI::Xaml::Controls::SelectionChangedEventArgs& eventArgs);
@@ -200,6 +200,7 @@ namespace winrt::TerminalApp::implementation
void _HandleFind(const IInspectable& sender, const TerminalApp::ActionEventArgs& args);
void _HandleResetFontSize(const IInspectable& sender, const TerminalApp::ActionEventArgs& args);
void _HandleToggleFullscreen(const IInspectable& sender, const TerminalApp::ActionEventArgs& args);
+ void _HandleMoveSelectionPoint(const IInspectable& sender, const TerminalApp::ActionEventArgs& args);
void _HandleSetTabColor(const IInspectable& sender, const TerminalApp::ActionEventArgs& args);
void _HandleOpenTabColorPicker(const IInspectable& sender, const TerminalApp::ActionEventArgs& args);
void _HandleRenameTab(const IInspectable& sender, const TerminalApp::ActionEventArgs& args);
diff --git a/src/cascadia/TerminalApp/defaults.json b/src/cascadia/TerminalApp/defaults.json
index e3df4f19b8f..c6aa0a8843f 100644
--- a/src/cascadia/TerminalApp/defaults.json
+++ b/src/cascadia/TerminalApp/defaults.json
@@ -327,6 +327,23 @@
{ "command": "paste", "keys": "ctrl+shift+v" },
{ "command": "paste", "keys": "shift+insert" },
+ // Selection Modification (by cell)
+ { "command": { "action": "moveSelectionPoint", "direction": "down", "expansionMode": "cell" }, "keys": ["shift+down"] },
+ { "command": { "action": "moveSelectionPoint", "direction": "up", "expansionMode": "cell" }, "keys": ["shift+up"] },
+ { "command": { "action": "moveSelectionPoint", "direction": "left", "expansionMode": "cell" }, "keys": ["shift+left"] },
+ { "command": { "action": "moveSelectionPoint", "direction": "right", "expansionMode": "cell" }, "keys": ["shift+right"] },
+ // Selection Modification (by word)
+ { "command": { "action": "moveSelectionPoint", "direction": "left", "expansionMode": "word" }, "keys": ["ctrl+shift+left"] },
+ { "command": { "action": "moveSelectionPoint", "direction": "right", "expansionMode": "word" }, "keys": ["ctrl+shift+right"] },
+ // Selection Modification (by viewport)
+ { "command": { "action": "moveSelectionPoint", "direction": "left", "expansionMode": "viewport" }, "keys": ["shift+home"] },
+ { "command": { "action": "moveSelectionPoint", "direction": "right", "expansionMode": "viewport" }, "keys": ["shift+end"] },
+ { "command": { "action": "moveSelectionPoint", "direction": "up", "expansionMode": "viewport" }, "keys": ["shift+pgup"] },
+ { "command": { "action": "moveSelectionPoint", "direction": "down", "expansionMode": "viewport" }, "keys": ["shift+pgdn"] },
+ // Selection Modification (by buffer)
+ { "command": { "action": "moveSelectionPoint", "direction": "up", "expansionMode": "buffer" }, "keys": ["ctrl+shift+home"] },
+ { "command": { "action": "moveSelectionPoint", "direction": "down", "expansionMode": "buffer" }, "keys": ["ctrl+shift+end"] },
+
// Scrollback
{ "command": "scrollDown", "keys": "ctrl+shift+down" },
{ "command": "scrollDownPage", "keys": "ctrl+shift+pgdn" },
diff --git a/src/cascadia/TerminalControl/TermControl.cpp b/src/cascadia/TerminalControl/TermControl.cpp
index 0d8fa29e2b4..0814eb16f25 100644
--- a/src/cascadia/TerminalControl/TermControl.cpp
+++ b/src/cascadia/TerminalControl/TermControl.cpp
@@ -829,7 +829,6 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
// details
if (modifiers.IsAltPressed() &&
(e.OriginalKey() >= VirtualKey::NumberPad0 && e.OriginalKey() <= VirtualKey::NumberPad9))
-
{
e.Handled(true);
return;
@@ -1078,18 +1077,18 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
const unsigned int MAX_CLICK_COUNT = 3;
const auto multiClickMapper = clickCount > MAX_CLICK_COUNT ? ((clickCount + MAX_CLICK_COUNT - 1) % MAX_CLICK_COUNT) + 1 : clickCount;
- ::Terminal::SelectionExpansionMode mode = ::Terminal::SelectionExpansionMode::Cell;
+ SelectionExpansionMode mode = SelectionExpansionMode::Cell;
if (multiClickMapper == 1)
{
- mode = ::Terminal::SelectionExpansionMode::Cell;
+ mode = SelectionExpansionMode::Cell;
}
else if (multiClickMapper == 2)
{
- mode = ::Terminal::SelectionExpansionMode::Word;
+ mode = SelectionExpansionMode::Word;
}
else if (multiClickMapper == 3)
{
- mode = ::Terminal::SelectionExpansionMode::Line;
+ mode = SelectionExpansionMode::Line;
}
// Update the selection appropriately
@@ -1099,7 +1098,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
_terminal->SetSelectionEnd(terminalPosition, mode);
_selectionNeedsToBeCopied = true;
}
- else if (mode == ::Terminal::SelectionExpansionMode::Cell)
+ else if (mode == SelectionExpansionMode::Cell)
{
// Single Click: reset the selection and begin a new one
_terminal->ClearSelection();
@@ -1469,6 +1468,26 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
_SetFontSize(newSize);
}
+ // Method Description:
+ // - Moves the selection endpoint in use. Used for Keyboard Selection.
+ // Arguments:
+ // - dir: The direction to move the selection anchor in
+ // - expansionMode: The movement mode in use for movement
+ // Return Value:
+ // - true, if the action was handled. false, otherwise.
+ bool TermControl::MoveSelectionPoint(Direction dir, SelectionExpansionMode mode)
+ {
+ // no selection/direction --> not valid
+ if (_terminal == nullptr || !_terminal->IsSelectionActive() || dir == Direction::None)
+ {
+ return false;
+ }
+
+ _terminal->MoveSelectionAnchor(dir, mode);
+ _renderer->TriggerSelection();
+ return true;
+ }
+
// Method Description:
// - Scroll the visible viewport in response to a mouse wheel event.
// Arguments:
diff --git a/src/cascadia/TerminalControl/TermControl.h b/src/cascadia/TerminalControl/TermControl.h
index f2805b5f338..512c57834c4 100644
--- a/src/cascadia/TerminalControl/TermControl.h
+++ b/src/cascadia/TerminalControl/TermControl.h
@@ -77,6 +77,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
void AdjustFontSize(int fontSizeDelta);
void ResetFontSize();
+ bool MoveSelectionPoint(Settings::Direction dir, Settings::SelectionExpansionMode expansionMode);
winrt::fire_and_forget RenderEngineSwapChainChanged();
void _AttachDxgiSwapChainToXaml(IDXGISwapChain1* swapChain);
diff --git a/src/cascadia/TerminalControl/TermControl.idl b/src/cascadia/TerminalControl/TermControl.idl
index 7c8712f4242..b57f9484a4b 100644
--- a/src/cascadia/TerminalControl/TermControl.idl
+++ b/src/cascadia/TerminalControl/TermControl.idl
@@ -54,6 +54,7 @@ namespace Microsoft.Terminal.TerminalControl
Boolean CopySelectionToClipboard(Boolean collapseText);
void PasteTextFromClipboard();
+ Boolean MoveSelectionPoint(Microsoft.Terminal.Settings.Direction direction, Microsoft.Terminal.Settings.SelectionExpansionMode expansionMode);
void Close();
Windows.Foundation.Size CharacterDimensions { get; };
Windows.Foundation.Size MinimumSize { get; };
diff --git a/src/cascadia/TerminalCore/Terminal.cpp b/src/cascadia/TerminalCore/Terminal.cpp
index b12e07628df..4c71fae4c1f 100644
--- a/src/cascadia/TerminalCore/Terminal.cpp
+++ b/src/cascadia/TerminalCore/Terminal.cpp
@@ -10,8 +10,6 @@
#include "../../inc/argb.h"
#include "../../types/inc/utils.hpp"
-#include "winrt/Microsoft.Terminal.Settings.h"
-
using namespace winrt::Microsoft::Terminal::Settings;
using namespace Microsoft::Terminal::Core;
using namespace Microsoft::Console;
diff --git a/src/cascadia/TerminalCore/Terminal.hpp b/src/cascadia/TerminalCore/Terminal.hpp
index 5b855a99ec6..14b599619cb 100644
--- a/src/cascadia/TerminalCore/Terminal.hpp
+++ b/src/cascadia/TerminalCore/Terminal.hpp
@@ -16,6 +16,8 @@
#include "../../cascadia/terminalcore/ITerminalApi.hpp"
#include "../../cascadia/terminalcore/ITerminalInput.hpp"
+#include "winrt/Microsoft.Terminal.Settings.h"
+
// You have to forward decl the ICoreSettings here, instead of including the header.
// If you include the header, there will be compilation errors with other
// headers that include Terminal.hpp
@@ -181,17 +183,14 @@ class Microsoft::Terminal::Core::Terminal final :
#pragma region TextSelection
// These methods are defined in TerminalSelection.cpp
- enum class SelectionExpansionMode
- {
- Cell,
- Word,
- Line
- };
- void MultiClickSelection(const COORD viewportPos, SelectionExpansionMode expansionMode);
+ void MultiClickSelection(const COORD viewportPos, winrt::Microsoft::Terminal::Settings::SelectionExpansionMode expansionMode);
void SetSelectionAnchor(const COORD position);
- void SetSelectionEnd(const COORD position, std::optional newExpansionMode = std::nullopt);
+ void SetSelectionEnd(const COORD position, std::optional newExpansionMode = std::nullopt);
void SetBlockSelection(const bool isEnabled) noexcept;
+ void MoveSelectionAnchor(winrt::Microsoft::Terminal::Settings::Direction dir,
+ winrt::Microsoft::Terminal::Settings::SelectionExpansionMode mode,
+ winrt::Microsoft::Terminal::Settings::SelectionEndpoint target = winrt::Microsoft::Terminal::Settings::SelectionEndpoint::End);
const TextBuffer::TextAndColor RetrieveSelectedTextFromBuffer(bool trimTrailingWhitespace) const;
#pragma endregion
@@ -230,7 +229,7 @@ class Microsoft::Terminal::Core::Terminal final :
std::optional _selection;
bool _blockSelection;
std::wstring _wordDelimiters;
- SelectionExpansionMode _multiClickSelectionMode;
+ winrt::Microsoft::Terminal::Settings::SelectionExpansionMode _multiClickSelectionMode;
#pragma endregion
std::shared_mutex _readWriteLock;
@@ -295,6 +294,12 @@ class Microsoft::Terminal::Core::Terminal final :
std::pair _PivotSelection(const COORD targetPos, bool& targetStart) const;
std::pair _ExpandSelectionAnchors(std::pair anchors) const;
COORD _ConvertToBufferCell(const COORD viewportPos) const;
+
+ // These methods are used by Keyboard Selection
+ void _UpdateAnchorByCell(winrt::Microsoft::Terminal::Settings::Direction dir, COORD& anchor);
+ void _UpdateAnchorByWord(winrt::Microsoft::Terminal::Settings::Direction dir, COORD& anchor, winrt::Microsoft::Terminal::Settings::SelectionEndpoint target = winrt::Microsoft::Terminal::Settings::SelectionEndpoint::End);
+ void _UpdateAnchorByViewport(winrt::Microsoft::Terminal::Settings::Direction dir, COORD& anchor);
+ void _UpdateAnchorByBuffer(winrt::Microsoft::Terminal::Settings::Direction dir, COORD& anchor);
#pragma endregion
#ifdef UNIT_TESTING
diff --git a/src/cascadia/TerminalCore/TerminalSelection.cpp b/src/cascadia/TerminalCore/TerminalSelection.cpp
index 7d383702775..c8428907bc9 100644
--- a/src/cascadia/TerminalCore/TerminalSelection.cpp
+++ b/src/cascadia/TerminalCore/TerminalSelection.cpp
@@ -6,6 +6,7 @@
#include "unicode.hpp"
using namespace Microsoft::Terminal::Core;
+using namespace winrt::Microsoft::Terminal::Settings;
/* Selection Pivot Description:
* The pivot helps properly update the selection when a user moves a selection over itself
@@ -266,7 +267,7 @@ const TextBuffer::TextAndColor Terminal::RetrieveSelectedTextFromBuffer(bool sin
// Method Description:
// - convert viewport position to the corresponding location on the buffer
// Arguments:
-// - viewportPos: a coordinate on the viewport
+// - viewportPos: a coordinate relative to the visible viewport
// Return Value:
// - the corresponding location on the buffer
COORD Terminal::_ConvertToBufferCell(const COORD viewportPos) const
@@ -288,3 +289,215 @@ void Terminal::ColorSelection(const COORD, const COORD, const TextAttribute)
{
THROW_HR(E_NOTIMPL);
}
+
+// Method Description:
+// - update _selection's endpoint according to the direction provided.
+// It is moved according the the expansion mode.
+// Arguments:
+// - dir: the direction that the selection endpoint will attempt to move to
+// - mode: the selection expansion mode that the selection anchor will adhere to
+// Return Value:
+// -
+void Terminal::MoveSelectionAnchor(Direction dir, SelectionExpansionMode mode, SelectionEndpoint target)
+{
+ COORD endpoint = ((target == SelectionEndpoint::Start) ? _selection->start : _selection->end);
+
+ switch (mode)
+ {
+ case SelectionExpansionMode::Cell:
+ _UpdateAnchorByCell(dir, endpoint);
+ break;
+ case SelectionExpansionMode::Word:
+ _UpdateAnchorByWord(dir, endpoint, target);
+ break;
+ case SelectionExpansionMode::Viewport:
+ _UpdateAnchorByViewport(dir, endpoint);
+ break;
+ case SelectionExpansionMode::Buffer:
+ _UpdateAnchorByBuffer(dir, endpoint);
+ break;
+ default:
+ // the provided selection expansion mode is not supported
+ THROW_HR(E_NOTIMPL);
+ return;
+ }
+
+ // scroll if necessary
+ bool notifyScroll = false;
+ if (endpoint.Y < _VisibleStartIndex())
+ {
+ _scrollOffset = ViewStartIndex() - endpoint.Y;
+ notifyScroll = true;
+ }
+ else if (endpoint.Y > _VisibleEndIndex())
+ {
+ _scrollOffset = std::max(0, ViewStartIndex() - endpoint.Y);
+ notifyScroll = true;
+ }
+
+ if (notifyScroll)
+ {
+ // TODO CARLOS: I need to learn how to do TriggerScroll here properly
+ _buffer->GetRenderTarget().TriggerRedrawAll();
+ _NotifyScrollEvent();
+ }
+
+ // update internal state of selection anchor and vertical offset
+ if (target == SelectionEndpoint::Start)
+ {
+ _selection->start = endpoint;
+ }
+ else
+ {
+ _selection->end = endpoint;
+ }
+}
+
+// Method Description:
+// - update the endSelectionPosition anchor by one cell according to the direction provided.
+// Arguments:
+// - dir: the direction that the selection anchor will attempt to move to
+// Return Value:
+// -
+void Terminal::_UpdateAnchorByCell(Direction dir, COORD& anchor)
+{
+ auto bufferViewport = _buffer->GetSize();
+ switch (dir)
+ {
+ case Direction::Left:
+ bufferViewport.DecrementInBounds(anchor);
+ break;
+ case Direction::Right:
+ bufferViewport.IncrementInBounds(anchor);
+ break;
+ case Direction::Up:
+ THROW_IF_FAILED(ShortSub(anchor.Y, 1, &anchor.Y));
+ break;
+ case Direction::Down:
+ THROW_IF_FAILED(ShortAdd(anchor.Y, 1, &anchor.Y));
+ break;
+ default:
+ // direction is not supported.
+ THROW_HR(E_NOTIMPL);
+ return;
+ }
+}
+
+// Method Description:
+// - update the endSelectionPosition anchor by one word according to the direction provided.
+// Arguments:
+// - dir: the direction that the selection anchor will attempt to move to
+// Return Value:
+// -
+void Terminal::_UpdateAnchorByWord(Direction dir, COORD& anchor, SelectionEndpoint target)
+{
+ // we need this to be able to compare it later
+ // NOTE: if target = START --> return END; else return START
+ COORD otherSelectionAnchor = ((target == SelectionEndpoint::Start) ? _selection->end : _selection->start);
+
+ const auto bufferViewport = _buffer->GetSize();
+ const auto comparison = bufferViewport.CompareInBounds(anchor, otherSelectionAnchor);
+ switch (dir)
+ {
+ case Direction::Up:
+ THROW_IF_FAILED(ShortSub(anchor.Y, 1, &anchor.Y));
+ bufferViewport.Clamp(anchor);
+ case Direction::Left:
+ if (comparison < 0)
+ {
+ // get on new run, before expanding left
+ bufferViewport.DecrementInBounds(anchor);
+ }
+ anchor = _buffer->GetWordStart(anchor, _wordDelimiters);
+ if (comparison > 0)
+ {
+ // get off of run, after expanding left
+ bufferViewport.DecrementInBounds(anchor);
+ }
+ break;
+ case Direction::Down:
+ THROW_IF_FAILED(ShortAdd(anchor.Y, 1, &anchor.Y));
+ bufferViewport.Clamp(anchor);
+ case Direction::Right:
+ if (comparison > 0)
+ {
+ // get on new run, before expanding left
+ bufferViewport.IncrementInBounds(anchor);
+ }
+ anchor = _buffer->GetWordEnd(anchor, _wordDelimiters);
+ if (comparison < 0)
+ {
+ // get off of run, after expanding left
+ bufferViewport.IncrementInBounds(anchor);
+ }
+ break;
+ default:
+ // direction is not supported.
+ THROW_HR(E_NOTIMPL);
+ return;
+ }
+}
+
+// Method Description:
+// - update the endSelectionPosition anchor by one viewport according to the direction provided.
+// Arguments:
+// - dir: the direction that the selection anchor will attempt to move to
+// Return Value:
+// -
+void Terminal::_UpdateAnchorByViewport(Direction dir, COORD& anchor)
+{
+ const auto bufferViewport = _buffer->GetSize();
+ switch (dir)
+ {
+ case Direction::Up:
+ THROW_IF_FAILED(ShortSub(anchor.Y, _mutableViewport.Height(), &anchor.Y));
+ if (!bufferViewport.IsInBounds(anchor))
+ {
+ anchor = bufferViewport.Origin();
+ }
+ break;
+ case Direction::Down:
+ THROW_IF_FAILED(ShortAdd(anchor.Y, _mutableViewport.Height(), &anchor.Y));
+ if (!bufferViewport.IsInBounds(anchor))
+ {
+ anchor = { _mutableViewport.RightInclusive(), _mutableViewport.BottomInclusive() };
+ }
+ break;
+ case Direction::Left:
+ anchor.X = _mutableViewport.Left();
+ break;
+ case Direction::Right:
+ anchor.X = _mutableViewport.RightInclusive();
+ break;
+ default:
+ // direction is not supported.
+ THROW_HR(E_NOTIMPL);
+ return;
+ }
+}
+
+// Method Description:
+// - update the endSelectionPosition anchor by the size of the buffer according to the direction provided.
+// Arguments:
+// - dir: the direction that the selection anchor will attempt to move to
+// Return Value:
+// -
+void Terminal::_UpdateAnchorByBuffer(Direction dir, COORD& anchor)
+{
+ const auto bufferViewport = _buffer->GetSize();
+ switch (dir)
+ {
+ case Direction::Up:
+ anchor = bufferViewport.Origin();
+ break;
+ case Direction::Down:
+ anchor = { bufferViewport.RightInclusive(), bufferViewport.BottomInclusive() };
+ break;
+ case Direction::Left:
+ case Direction::Right:
+ default:
+ // direction is not supported.
+ THROW_HR(E_NOTIMPL);
+ return;
+ }
+}
diff --git a/src/cascadia/TerminalCore/terminalrenderdata.cpp b/src/cascadia/TerminalCore/terminalrenderdata.cpp
index 17b57a28240..fb38993636a 100644
--- a/src/cascadia/TerminalCore/terminalrenderdata.cpp
+++ b/src/cascadia/TerminalCore/terminalrenderdata.cpp
@@ -4,6 +4,8 @@
#include "pch.h"
#include "Terminal.hpp"
#include
+
+using namespace winrt::Microsoft::Terminal::Settings;
using namespace Microsoft::Terminal::Core;
using namespace Microsoft::Console::Types;
using namespace Microsoft::Console::Render;
diff --git a/src/cascadia/TerminalSettings/ICoreSettings.idl b/src/cascadia/TerminalSettings/ICoreSettings.idl
index f1c055cc490..317baab03bf 100644
--- a/src/cascadia/TerminalSettings/ICoreSettings.idl
+++ b/src/cascadia/TerminalSettings/ICoreSettings.idl
@@ -12,6 +12,30 @@ namespace Microsoft.Terminal.Settings
EmptyBox
};
+ enum Direction
+ {
+ None = 0,
+ Left,
+ Right,
+ Up,
+ Down
+ };
+
+ enum SelectionExpansionMode
+ {
+ Cell = 0,
+ Word,
+ Line,
+ Viewport,
+ Buffer
+ };
+
+ enum SelectionEndpoint
+ {
+ End = 0,
+ Start
+ };
+
interface ICoreSettings
{
UInt32 DefaultForeground;
diff --git a/src/cascadia/TerminalSettings/TerminalSettings.idl b/src/cascadia/TerminalSettings/TerminalSettings.idl
index 15d265b1a9e..c768342ce5e 100644
--- a/src/cascadia/TerminalSettings/TerminalSettings.idl
+++ b/src/cascadia/TerminalSettings/TerminalSettings.idl
@@ -6,6 +6,27 @@ import "IControlSettings.idl";
namespace Microsoft.Terminal.Settings
{
+ enum SplitState
+ {
+ Automatic = -1,
+ None = 0,
+ Vertical = 1,
+ Horizontal = 2
+ };
+
+ enum SplitType
+ {
+ Manual = 0,
+ Duplicate = 1
+ };
+
+ enum SettingsTarget
+ {
+ SettingsFile = 0,
+ DefaultsFile,
+ AllFiles
+ };
+
// Class Description:
// TerminalSettings encapsulates all settings that control the
// TermControl's behavior. In these settings there is both the entirety
@@ -14,9 +35,7 @@ namespace Microsoft.Terminal.Settings
// settings it contains, in combination with the global settings.
// The TerminalControl will pull settings it requires from this object,
// and pass along the Core properties to the terminal core.
- [default_interface]
- runtimeclass TerminalSettings : ICoreSettings,
- IControlSettings
+ [default_interface] runtimeclass TerminalSettings : ICoreSettings, IControlSettings
{
TerminalSettings();
};
diff --git a/src/cascadia/UnitTests_TerminalCore/SelectionTest.cpp b/src/cascadia/UnitTests_TerminalCore/SelectionTest.cpp
index 39f78b0b41c..8078b8763b4 100644
--- a/src/cascadia/UnitTests_TerminalCore/SelectionTest.cpp
+++ b/src/cascadia/UnitTests_TerminalCore/SelectionTest.cpp
@@ -44,6 +44,22 @@ namespace TerminalCoreUnitTests
VERIFY_ARE_EQUAL(selection, expected);
}
+ void ValidateMultiRowSelection(Terminal& term, std::vector expected)
+ {
+ // Simulate renderer calling TriggerSelection and acquiring selection area
+ auto selectionRects = term.GetSelectionRects();
+
+ VERIFY_ARE_EQUAL(selectionRects.size(), expected.size());
+ const auto viewport = term.GetViewport();
+
+ // Validate selection area
+ for (size_t i = 0; i < selectionRects.size(); ++i)
+ {
+ auto selection = viewport.ConvertToOrigin(selectionRects.at(i)).ToInclusive();
+ VERIFY_ARE_EQUAL(selection, expected.at(i));
+ }
+ }
+
TEST_METHOD(SelectUnit)
{
Terminal term;
@@ -673,12 +689,90 @@ namespace TerminalCoreUnitTests
VERIFY_ARE_EQUAL(selection, SMALL_RECT({ 0, 11, 99, 11 }));
}
- TEST_METHOD(ShiftClick)
+ TEST_METHOD(KeyboardSelection_MoveByCell)
{
Terminal term;
DummyRenderTarget emptyRT;
term.Create({ 100, 100 }, 0, emptyRT);
+ auto resetState = [&]() {
+ const auto start = COORD{ 3, 10 };
+ const auto end = COORD{ 7, 10 };
+ term.SetSelectionAnchor(start);
+ term.SetEndSelectionPosition(end);
+ ValidateSingleRowSelection(term, { 3, 10, 7, 10 });
+ };
+
+ // Left
+ {
+ resetState();
+ Log::Comment(L"Move end by cell to the left");
+ term.MoveSelectionAnchor(Terminal::Direction::Left,
+ Terminal::SelectionExpansionMode::Cell,
+ Terminal::SelectionAnchorTarget::End);
+ ValidateSingleRowSelection(term, { 3, 10, 6, 10 });
+
+ Log::Comment(L"Move start by cell to the left");
+ term.MoveSelectionAnchor(Terminal::Direction::Left,
+ Terminal::SelectionExpansionMode::Cell,
+ Terminal::SelectionAnchorTarget::Start);
+ ValidateSingleRowSelection(term, { 2, 10, 6, 10 });
+ }
+
+ // Right
+ {
+ resetState();
+ Log::Comment(L"Move end by cell to the right");
+ term.MoveSelectionAnchor(Terminal::Direction::Right,
+ Terminal::SelectionExpansionMode::Cell,
+ Terminal::SelectionAnchorTarget::End);
+ ValidateSingleRowSelection(term, { 3, 10, 8, 10 });
+
+ Log::Comment(L"Move start by cell to the right");
+ term.MoveSelectionAnchor(Terminal::Direction::Right,
+ Terminal::SelectionExpansionMode::Cell,
+ Terminal::SelectionAnchorTarget::Start);
+ ValidateSingleRowSelection(term, { 4, 10, 8, 10 });
+ }
+
+ // Up
+ {
+ resetState();
+ Log::Comment(L"Move end by cell up");
+ term.MoveSelectionAnchor(Terminal::Direction::Up,
+ Terminal::SelectionExpansionMode::Cell,
+ Terminal::SelectionAnchorTarget::End);
+ ValidateMultiRowSelection(term, { { 7, 9, 99, 9 }, { 0, 10, 3, 10 } });
+
+ Log::Comment(L"Move start by cell up");
+ term.MoveSelectionAnchor(Terminal::Direction::Up,
+ Terminal::SelectionExpansionMode::Cell,
+ Terminal::SelectionAnchorTarget::Start);
+ ValidateSingleRowSelection(term, { 3, 9, 7, 9 });
+ }
+
+ // Down
+ {
+ resetState();
+ Log::Comment(L"Move end by cell down");
+ term.MoveSelectionAnchor(Terminal::Direction::Down,
+ Terminal::SelectionExpansionMode::Cell,
+ Terminal::SelectionAnchorTarget::End);
+ ValidateMultiRowSelection(term, { { 3, 10, 99, 10 }, { 0, 11, 7, 11 } });
+
+ Log::Comment(L"Move start by cell down");
+ term.MoveSelectionAnchor(Terminal::Direction::Down,
+ Terminal::SelectionExpansionMode::Cell,
+ Terminal::SelectionAnchorTarget::Start);
+ ValidateSingleRowSelection(term, { 3, 11, 7, 11 });
+ }
+ }
+
+ TEST_METHOD(ShiftClick)
+ {
+ Terminal term;
+ DummyRenderTarget emptyRT;
+ term.Create({ 100, 100 }, 0, emptyRT);
// set word delimiters for terminal
auto settings = winrt::make(0, 100, 100);
term.UpdateSettings(settings);
@@ -790,12 +884,90 @@ namespace TerminalCoreUnitTests
}
}
- TEST_METHOD(Pivot)
+ TEST_METHOD(KeyboardSelection_MoveByWord)
{
Terminal term;
DummyRenderTarget emptyRT;
term.Create({ 100, 100 }, 0, emptyRT);
+ auto resetState = [&]() {
+ const auto start = COORD{ 3, 10 };
+ const auto end = COORD{ 7, 10 };
+ term.SetSelectionAnchor(start);
+ term.SetEndSelectionPosition(end);
+ ValidateSingleRowSelection(term, { 3, 10, 7, 10 });
+ };
+
+ // Left
+ {
+ resetState();
+ Log::Comment(L"Move end by word to the left");
+ term.MoveSelectionAnchor(Terminal::Direction::Left,
+ Terminal::SelectionExpansionMode::Word,
+ Terminal::SelectionAnchorTarget::End);
+ ValidateSingleRowSelection(term, { 0, 10, 7, 10 });
+
+ Log::Comment(L"Move start by word to the left");
+ term.MoveSelectionAnchor(Terminal::Direction::Left,
+ Terminal::SelectionExpansionMode::Word,
+ Terminal::SelectionAnchorTarget::Start);
+ ValidateSingleRowSelection(term, { 0, 10, 0, 10 });
+ }
+
+ // Right
+ {
+ resetState();
+ Log::Comment(L"Move end by word to the right");
+ term.MoveSelectionAnchor(Terminal::Direction::Right,
+ Terminal::SelectionExpansionMode::Word,
+ Terminal::SelectionAnchorTarget::End);
+ ValidateSingleRowSelection(term, { 3, 10, 99, 10 });
+
+ Log::Comment(L"Move start by word to the right");
+ term.MoveSelectionAnchor(Terminal::Direction::Right,
+ Terminal::SelectionExpansionMode::Word,
+ Terminal::SelectionAnchorTarget::Start);
+ ValidateSingleRowSelection(term, { 99, 10, 99, 10 });
+ }
+
+ // Up
+ {
+ resetState();
+ Log::Comment(L"Move end by word up");
+ term.MoveSelectionAnchor(Terminal::Direction::Up,
+ Terminal::SelectionExpansionMode::Word,
+ Terminal::SelectionAnchorTarget::End);
+ ValidateMultiRowSelection(term, { { 0, 9, 99, 9 }, { 0, 10, 3, 10 } });
+
+ Log::Comment(L"Move start by word up");
+ term.MoveSelectionAnchor(Terminal::Direction::Up,
+ Terminal::SelectionExpansionMode::Word,
+ Terminal::SelectionAnchorTarget::Start);
+ ValidateSingleRowSelection(term, { 0, 9, 99, 9 });
+ }
+
+ // Down
+ {
+ resetState();
+ Log::Comment(L"Move end by word down");
+ term.MoveSelectionAnchor(Terminal::Direction::Down,
+ Terminal::SelectionExpansionMode::Word,
+ Terminal::SelectionAnchorTarget::End);
+ ValidateMultiRowSelection(term, { { 3, 10, 99, 10 }, { 0, 11, 99, 11 } });
+
+ Log::Comment(L"Move start by word down");
+ term.MoveSelectionAnchor(Terminal::Direction::Down,
+ Terminal::SelectionExpansionMode::Word,
+ Terminal::SelectionAnchorTarget::Start);
+ ValidateSingleRowSelection(term, { 0, 11, 99, 11 });
+ }
+ }
+
+ TEST_METHOD(Pivot)
+ {
+ Terminal term;
+ DummyRenderTarget emptyRT;
+ term.Create({ 100, 100 }, 0, emptyRT);
// Step 1: Create a selection
{
// (10,10) to (20, 10)