Merge remote-tracking branch 'origin/main' into dev/migrie/f/just-elevated-state-2
This commit is contained in:
commit
56850639c5
3
.github/actions/spelling/allow/allow.txt
vendored
3
.github/actions/spelling/allow/allow.txt
vendored
|
@ -36,6 +36,9 @@ liga
|
|||
lje
|
||||
locl
|
||||
lorem
|
||||
Llast
|
||||
Lmid
|
||||
Lorigin
|
||||
maxed
|
||||
mkmk
|
||||
mru
|
||||
|
|
1
.github/actions/spelling/allow/apis.txt
vendored
1
.github/actions/spelling/allow/apis.txt
vendored
|
@ -69,6 +69,7 @@ iosfwd
|
|||
IPackage
|
||||
IPeasant
|
||||
isspace
|
||||
ISetup
|
||||
IStorage
|
||||
istream
|
||||
IStringable
|
||||
|
|
1
.github/actions/spelling/expect/expect.txt
vendored
1
.github/actions/spelling/expect/expect.txt
vendored
|
@ -2578,6 +2578,7 @@ VREDRAW
|
|||
vsc
|
||||
vscprintf
|
||||
VSCROLL
|
||||
vsdevshell
|
||||
vsinfo
|
||||
vsnprintf
|
||||
vso
|
||||
|
|
|
@ -346,11 +346,13 @@
|
|||
],
|
||||
"type": "string"
|
||||
},
|
||||
"SplitState": {
|
||||
"SplitDirection": {
|
||||
"enum": [
|
||||
"vertical",
|
||||
"horizontal",
|
||||
"auto"
|
||||
"auto",
|
||||
"up",
|
||||
"right",
|
||||
"down",
|
||||
"left"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
|
@ -629,9 +631,9 @@
|
|||
"properties": {
|
||||
"action": { "type": "string", "pattern": "splitPane" },
|
||||
"split": {
|
||||
"$ref": "#/definitions/SplitState",
|
||||
"$ref": "#/definitions/SplitDirection",
|
||||
"default": "auto",
|
||||
"description": "The orientation to split the pane in. Possible values:\n -\"auto\" (splits pane based on remaining space)\n -\"horizontal\" (think [-])\n -\"vertical\" (think [|])"
|
||||
"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)"
|
||||
},
|
||||
"splitMode": {
|
||||
"default": "duplicate",
|
||||
|
@ -1262,14 +1264,14 @@
|
|||
"type": [ "integer", "string" ],
|
||||
"deprecated": true
|
||||
},
|
||||
"minimizeToTray": {
|
||||
"minimizeToNotificationArea": {
|
||||
"default": "false",
|
||||
"description": "When set to true, minimizing a Terminal window will no longer appear in the taskbar. Instead, a Terminal icon will appear in the system tray through which the user can access their windows.",
|
||||
"description": "When set to true, minimizing a Terminal window will no longer appear in the taskbar. Instead, a Terminal icon will appear in the notification area through which the user can access their windows.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"alwaysShowTrayIcon": {
|
||||
"alwaysShowNotificationIcon": {
|
||||
"default": "false",
|
||||
"description": "When set to true, the Terminal's tray icon will always be shown in the system tray.",
|
||||
"description": "When set to true, the Terminal's notification icon will always be shown in the notification area.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"useAcrylicInTabRow": {
|
||||
|
|
|
@ -1057,9 +1057,10 @@ const DelimiterClass TextBuffer::_GetDelimiterClassAt(const COORD pos, const std
|
|||
// - accessibilityMode - when enabled, we continue expanding left until we are at the beginning of a readable word.
|
||||
// Otherwise, expand left until a character of a new delimiter class is found
|
||||
// (or a row boundary is encountered)
|
||||
// - limitOptional - (optional) the last possible position in the buffer that can be explored. This can be used to improve performance.
|
||||
// Return Value:
|
||||
// - The COORD for the first character on the "word" (inclusive)
|
||||
const COORD TextBuffer::GetWordStart(const COORD target, const std::wstring_view wordDelimiters, bool accessibilityMode) const
|
||||
const COORD TextBuffer::GetWordStart(const COORD target, const std::wstring_view wordDelimiters, bool accessibilityMode, std::optional<til::point> limitOptional) const
|
||||
{
|
||||
// Consider a buffer with this text in it:
|
||||
// " word other "
|
||||
|
@ -1072,10 +1073,9 @@ const COORD TextBuffer::GetWordStart(const COORD target, const std::wstring_view
|
|||
// NOTE: the start anchor (this one) is inclusive, whereas the end anchor (GetWordEnd) is exclusive
|
||||
|
||||
#pragma warning(suppress : 26496)
|
||||
// GH#7664: Treat EndExclusive as EndInclusive so
|
||||
// that it actually points to a space in the buffer
|
||||
auto copy{ target };
|
||||
const auto bufferSize{ GetSize() };
|
||||
const auto limit{ limitOptional.value_or(bufferSize.EndExclusive()) };
|
||||
if (target == bufferSize.Origin())
|
||||
{
|
||||
// can't expand left
|
||||
|
@ -1083,9 +1083,15 @@ const COORD TextBuffer::GetWordStart(const COORD target, const std::wstring_view
|
|||
}
|
||||
else if (target == bufferSize.EndExclusive())
|
||||
{
|
||||
// treat EndExclusive as EndInclusive
|
||||
// GH#7664: Treat EndExclusive as EndInclusive so
|
||||
// that it actually points to a space in the buffer
|
||||
copy = { bufferSize.RightInclusive(), bufferSize.BottomInclusive() };
|
||||
}
|
||||
else if (bufferSize.CompareInBounds(target, limit, true) >= 0)
|
||||
{
|
||||
// if at/past the limit --> clamp to limit
|
||||
copy = *limitOptional;
|
||||
}
|
||||
|
||||
if (accessibilityMode)
|
||||
{
|
||||
|
@ -1179,9 +1185,10 @@ const COORD TextBuffer::_GetWordStartForSelection(const COORD target, const std:
|
|||
// - accessibilityMode - when enabled, we continue expanding right until we are at the beginning of the next READABLE word
|
||||
// Otherwise, expand right until a character of a new delimiter class is found
|
||||
// (or a row boundary is encountered)
|
||||
// - limitOptional - (optional) the last possible position in the buffer that can be explored. This can be used to improve performance.
|
||||
// Return Value:
|
||||
// - The COORD for the last character on the "word" (inclusive)
|
||||
const COORD TextBuffer::GetWordEnd(const COORD target, const std::wstring_view wordDelimiters, bool accessibilityMode) const
|
||||
const COORD TextBuffer::GetWordEnd(const COORD target, const std::wstring_view wordDelimiters, bool accessibilityMode, std::optional<til::point> limitOptional) const
|
||||
{
|
||||
// Consider a buffer with this text in it:
|
||||
// " word other "
|
||||
|
@ -1193,16 +1200,17 @@ const COORD TextBuffer::GetWordEnd(const COORD target, const std::wstring_view w
|
|||
// so the words in the example include ["word ", "other "]
|
||||
// NOTE: the end anchor (this one) is exclusive, whereas the start anchor (GetWordStart) is inclusive
|
||||
|
||||
// Already at the end. Can't move forward.
|
||||
if (target == GetSize().EndExclusive())
|
||||
// Already at/past the limit. Can't move forward.
|
||||
const auto bufferSize{ GetSize() };
|
||||
const auto limit{ limitOptional.value_or(bufferSize.EndExclusive()) };
|
||||
if (bufferSize.CompareInBounds(target, limit, true) >= 0)
|
||||
{
|
||||
return target;
|
||||
}
|
||||
|
||||
if (accessibilityMode)
|
||||
{
|
||||
const auto lastCharPos{ GetLastNonSpaceCharacter() };
|
||||
return _GetWordEndForAccessibility(target, wordDelimiters, lastCharPos);
|
||||
return _GetWordEndForAccessibility(target, wordDelimiters, limit);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1215,44 +1223,46 @@ const COORD TextBuffer::GetWordEnd(const COORD target, const std::wstring_view w
|
|||
// Arguments:
|
||||
// - target - a COORD on the word you are currently on
|
||||
// - wordDelimiters - what characters are we considering for the separation of words
|
||||
// - lastCharPos - the position of the last nonspace character in the text buffer (to improve performance)
|
||||
// - limit - the last "valid" position in the text buffer (to improve performance)
|
||||
// Return Value:
|
||||
// - The COORD for the first character of the next readable "word". If no next word, return one past the end of the buffer
|
||||
const COORD TextBuffer::_GetWordEndForAccessibility(const COORD target, const std::wstring_view wordDelimiters, const COORD lastCharPos) const
|
||||
const COORD TextBuffer::_GetWordEndForAccessibility(const COORD target, const std::wstring_view wordDelimiters, const COORD limit) const
|
||||
{
|
||||
const auto bufferSize = GetSize();
|
||||
COORD result = target;
|
||||
const auto bufferSize{ GetSize() };
|
||||
COORD result{ target };
|
||||
|
||||
// Check if we're already on/past the last RegularChar
|
||||
if (bufferSize.CompareInBounds(result, lastCharPos, true) >= 0)
|
||||
if (bufferSize.CompareInBounds(target, limit, true) >= 0)
|
||||
{
|
||||
return bufferSize.EndExclusive();
|
||||
// if we're already on/past the last RegularChar,
|
||||
// clamp result to that position
|
||||
result = limit;
|
||||
|
||||
// make the result exclusive
|
||||
bufferSize.IncrementInBounds(result, true);
|
||||
}
|
||||
|
||||
// ignore right boundary. Continue through readable text found
|
||||
while (_GetDelimiterClassAt(result, wordDelimiters) == DelimiterClass::RegularChar)
|
||||
else
|
||||
{
|
||||
if (!bufferSize.IncrementInBounds(result, true))
|
||||
auto iter{ GetCellDataAt(result, bufferSize) };
|
||||
while (iter && iter.Pos() != limit && _GetDelimiterClassAt(iter.Pos(), wordDelimiters) == DelimiterClass::RegularChar)
|
||||
{
|
||||
break;
|
||||
// Iterate through readable text
|
||||
++iter;
|
||||
}
|
||||
}
|
||||
|
||||
// we are already on/past the last RegularChar
|
||||
if (bufferSize.CompareInBounds(result, lastCharPos, true) >= 0)
|
||||
{
|
||||
return bufferSize.EndExclusive();
|
||||
}
|
||||
|
||||
// make sure we expand to the beginning of the NEXT word
|
||||
while (_GetDelimiterClassAt(result, wordDelimiters) != DelimiterClass::RegularChar)
|
||||
{
|
||||
if (!bufferSize.IncrementInBounds(result, true))
|
||||
while (iter && iter.Pos() != limit && _GetDelimiterClassAt(iter.Pos(), wordDelimiters) != DelimiterClass::RegularChar)
|
||||
{
|
||||
// we are at the EndInclusive COORD
|
||||
// this signifies that we must include the last char in the buffer
|
||||
// but the position of the COORD points to nothing
|
||||
break;
|
||||
// expand to the beginning of the NEXT word
|
||||
++iter;
|
||||
}
|
||||
|
||||
result = iter.Pos();
|
||||
|
||||
// Special case: we tried to move one past the end of the buffer,
|
||||
// but iter prevented that (because that pos doesn't exist).
|
||||
// Manually increment onto the EndExclusive point.
|
||||
if (!iter)
|
||||
{
|
||||
bufferSize.IncrementInBounds(result, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1345,18 +1355,20 @@ void TextBuffer::_PruneHyperlinks()
|
|||
// Arguments:
|
||||
// - pos - a COORD on the word you are currently on
|
||||
// - wordDelimiters - what characters are we considering for the separation of words
|
||||
// - lastCharPos - the position of the last nonspace character in the text buffer (to improve performance)
|
||||
// - limitOptional - (optional) the last possible position in the buffer that can be explored. This can be used to improve performance.
|
||||
// Return Value:
|
||||
// - true, if successfully updated pos. False, if we are unable to move (usually due to a buffer boundary)
|
||||
// - pos - The COORD for the first character on the "word" (inclusive)
|
||||
bool TextBuffer::MoveToNextWord(COORD& pos, const std::wstring_view wordDelimiters, COORD lastCharPos) const
|
||||
bool TextBuffer::MoveToNextWord(COORD& pos, const std::wstring_view wordDelimiters, std::optional<til::point> limitOptional) const
|
||||
{
|
||||
// move to the beginning of the next word
|
||||
// NOTE: _GetWordEnd...() returns the exclusive position of the "end of the word"
|
||||
// This is also the inclusive start of the next word.
|
||||
auto copy{ _GetWordEndForAccessibility(pos, wordDelimiters, lastCharPos) };
|
||||
const auto bufferSize{ GetSize() };
|
||||
const auto limit{ limitOptional.value_or(bufferSize.EndExclusive()) };
|
||||
const auto copy{ _GetWordEndForAccessibility(pos, wordDelimiters, limit) };
|
||||
|
||||
if (copy == GetSize().EndExclusive())
|
||||
if (bufferSize.CompareInBounds(copy, limit, true) >= 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -1393,19 +1405,23 @@ bool TextBuffer::MoveToPreviousWord(COORD& pos, std::wstring_view wordDelimiters
|
|||
// - Update pos to be the beginning of the current glyph/character. This is used for accessibility
|
||||
// Arguments:
|
||||
// - pos - a COORD on the word you are currently on
|
||||
// - limitOptional - (optional) the last possible position in the buffer that can be explored. This can be used to improve performance.
|
||||
// Return Value:
|
||||
// - pos - The COORD for the first cell of the current glyph (inclusive)
|
||||
const til::point TextBuffer::GetGlyphStart(const til::point pos) const
|
||||
const til::point TextBuffer::GetGlyphStart(const til::point pos, std::optional<til::point> limitOptional) const
|
||||
{
|
||||
COORD resultPos = pos;
|
||||
const auto bufferSize = GetSize();
|
||||
const auto limit{ limitOptional.value_or(bufferSize.EndExclusive()) };
|
||||
|
||||
if (resultPos == bufferSize.EndExclusive())
|
||||
// Clamp pos to limit
|
||||
if (bufferSize.CompareInBounds(resultPos, limit, true) > 0)
|
||||
{
|
||||
bufferSize.DecrementInBounds(resultPos, true);
|
||||
resultPos = limit;
|
||||
}
|
||||
|
||||
if (resultPos != bufferSize.EndExclusive() && GetCellDataAt(resultPos)->DbcsAttr().IsTrailing())
|
||||
// limit is exclusive, so we need to move back to be within valid bounds
|
||||
if (resultPos != limit && GetCellDataAt(resultPos)->DbcsAttr().IsTrailing())
|
||||
{
|
||||
bufferSize.DecrementInBounds(resultPos, true);
|
||||
}
|
||||
|
@ -1419,12 +1435,19 @@ const til::point TextBuffer::GetGlyphStart(const til::point pos) const
|
|||
// - pos - a COORD on the word you are currently on
|
||||
// Return Value:
|
||||
// - pos - The COORD for the last cell of the current glyph (exclusive)
|
||||
const til::point TextBuffer::GetGlyphEnd(const til::point pos) const
|
||||
const til::point TextBuffer::GetGlyphEnd(const til::point pos, std::optional<til::point> limitOptional) const
|
||||
{
|
||||
COORD resultPos = pos;
|
||||
|
||||
const auto bufferSize = GetSize();
|
||||
if (resultPos != bufferSize.EndExclusive() && GetCellDataAt(resultPos)->DbcsAttr().IsLeading())
|
||||
const auto limit{ limitOptional.value_or(bufferSize.EndExclusive()) };
|
||||
|
||||
// Clamp pos to limit
|
||||
if (bufferSize.CompareInBounds(resultPos, limit, true) > 0)
|
||||
{
|
||||
resultPos = limit;
|
||||
}
|
||||
|
||||
if (resultPos != limit && GetCellDataAt(resultPos)->DbcsAttr().IsLeading())
|
||||
{
|
||||
bufferSize.IncrementInBounds(resultPos, true);
|
||||
}
|
||||
|
@ -1438,29 +1461,43 @@ const til::point TextBuffer::GetGlyphEnd(const til::point pos) const
|
|||
// - Update pos to be the beginning of the next glyph/character. This is used for accessibility
|
||||
// Arguments:
|
||||
// - pos - a COORD on the word you are currently on
|
||||
// - allowBottomExclusive - allow the nonexistent end-of-buffer cell to be encountered
|
||||
// - allowExclusiveEnd - allow result to be the exclusive limit (one past limit)
|
||||
// - limit - boundaries for the iterator to operate within
|
||||
// Return Value:
|
||||
// - true, if successfully updated pos. False, if we are unable to move (usually due to a buffer boundary)
|
||||
// - pos - The COORD for the first cell of the current glyph (inclusive)
|
||||
bool TextBuffer::MoveToNextGlyph(til::point& pos, bool allowBottomExclusive) const
|
||||
bool TextBuffer::MoveToNextGlyph(til::point& pos, bool allowExclusiveEnd, std::optional<til::point> limitOptional) const
|
||||
{
|
||||
COORD resultPos = pos;
|
||||
const auto bufferSize = GetSize();
|
||||
const auto limit{ limitOptional.value_or(bufferSize.EndExclusive()) };
|
||||
|
||||
if (resultPos == GetSize().EndExclusive())
|
||||
const auto distanceToLimit{ bufferSize.CompareInBounds(pos, limit, true) };
|
||||
if (distanceToLimit >= 0)
|
||||
{
|
||||
// we're already at the end
|
||||
// Corner Case: we're on/past the limit
|
||||
// Clamp us to the limit
|
||||
pos = limit;
|
||||
return false;
|
||||
}
|
||||
else if (!allowExclusiveEnd && distanceToLimit == -1)
|
||||
{
|
||||
// Corner Case: we're just before the limit
|
||||
// and we are not allowed onto the exclusive end.
|
||||
// Fail to move.
|
||||
return false;
|
||||
}
|
||||
|
||||
// try to move. If we can't, we're done.
|
||||
const bool success = bufferSize.IncrementInBounds(resultPos, allowBottomExclusive);
|
||||
if (resultPos != bufferSize.EndExclusive() && GetCellDataAt(resultPos)->DbcsAttr().IsTrailing())
|
||||
// Try to move forward, but if we hit the buffer boundary, we fail to move.
|
||||
auto iter{ GetCellDataAt(pos, bufferSize) };
|
||||
const bool success{ ++iter };
|
||||
|
||||
// Move again if we're on a wide glyph
|
||||
if (success && iter->DbcsAttr().IsTrailing())
|
||||
{
|
||||
bufferSize.IncrementInBounds(resultPos, allowBottomExclusive);
|
||||
++iter;
|
||||
}
|
||||
|
||||
pos = resultPos;
|
||||
pos = iter.Pos();
|
||||
return success;
|
||||
}
|
||||
|
||||
|
@ -1471,12 +1508,21 @@ bool TextBuffer::MoveToNextGlyph(til::point& pos, bool allowBottomExclusive) con
|
|||
// Return Value:
|
||||
// - true, if successfully updated pos. False, if we are unable to move (usually due to a buffer boundary)
|
||||
// - pos - The COORD for the first cell of the previous glyph (inclusive)
|
||||
bool TextBuffer::MoveToPreviousGlyph(til::point& pos) const
|
||||
bool TextBuffer::MoveToPreviousGlyph(til::point& pos, std::optional<til::point> limitOptional) const
|
||||
{
|
||||
COORD resultPos = pos;
|
||||
const auto bufferSize = GetSize();
|
||||
const auto limit{ limitOptional.value_or(bufferSize.EndExclusive()) };
|
||||
|
||||
if (bufferSize.CompareInBounds(pos, limit, true) > 0)
|
||||
{
|
||||
// we're past the end
|
||||
// clamp us to the limit
|
||||
pos = limit;
|
||||
return true;
|
||||
}
|
||||
|
||||
// try to move. If we can't, we're done.
|
||||
const auto bufferSize = GetSize();
|
||||
const bool success = bufferSize.DecrementInBounds(resultPos, true);
|
||||
if (resultPos != bufferSize.EndExclusive() && GetCellDataAt(resultPos)->DbcsAttr().IsLeading())
|
||||
{
|
||||
|
|
|
@ -141,15 +141,15 @@ public:
|
|||
|
||||
Microsoft::Console::Render::IRenderTarget& GetRenderTarget() noexcept;
|
||||
|
||||
const COORD GetWordStart(const COORD target, const std::wstring_view wordDelimiters, bool accessibilityMode = false) const;
|
||||
const COORD GetWordEnd(const COORD target, const std::wstring_view wordDelimiters, bool accessibilityMode = false) const;
|
||||
bool MoveToNextWord(COORD& pos, const std::wstring_view wordDelimiters, COORD lastCharPos) const;
|
||||
const COORD GetWordStart(const COORD target, const std::wstring_view wordDelimiters, bool accessibilityMode = false, std::optional<til::point> limitOptional = std::nullopt) const;
|
||||
const COORD GetWordEnd(const COORD target, const std::wstring_view wordDelimiters, bool accessibilityMode = false, std::optional<til::point> limitOptional = std::nullopt) const;
|
||||
bool MoveToNextWord(COORD& pos, const std::wstring_view wordDelimiters, std::optional<til::point> limitOptional = std::nullopt) const;
|
||||
bool MoveToPreviousWord(COORD& pos, const std::wstring_view wordDelimiters) const;
|
||||
|
||||
const til::point GetGlyphStart(const til::point pos) const;
|
||||
const til::point GetGlyphEnd(const til::point pos) const;
|
||||
bool MoveToNextGlyph(til::point& pos, bool allowBottomExclusive = false) const;
|
||||
bool MoveToPreviousGlyph(til::point& pos) const;
|
||||
const til::point GetGlyphStart(const til::point pos, std::optional<til::point> limitOptional = std::nullopt) const;
|
||||
const til::point GetGlyphEnd(const til::point pos, std::optional<til::point> limitOptional = std::nullopt) const;
|
||||
bool MoveToNextGlyph(til::point& pos, bool allowBottomExclusive = false, std::optional<til::point> limitOptional = std::nullopt) const;
|
||||
bool MoveToPreviousGlyph(til::point& pos, std::optional<til::point> limitOptional = std::nullopt) const;
|
||||
|
||||
const std::vector<SMALL_RECT> GetTextRects(COORD start, COORD end, bool blockSelection, bool bufferCoordinates) const;
|
||||
|
||||
|
@ -242,7 +242,7 @@ private:
|
|||
const DelimiterClass _GetDelimiterClassAt(const COORD pos, const std::wstring_view wordDelimiters) const;
|
||||
const COORD _GetWordStartForAccessibility(const COORD target, const std::wstring_view wordDelimiters) const;
|
||||
const COORD _GetWordStartForSelection(const COORD target, const std::wstring_view wordDelimiters) const;
|
||||
const COORD _GetWordEndForAccessibility(const COORD target, const std::wstring_view wordDelimiters, const COORD lastCharPos) const;
|
||||
const COORD _GetWordEndForAccessibility(const COORD target, const std::wstring_view wordDelimiters, const COORD limit) const;
|
||||
const COORD _GetWordEndForSelection(const COORD target, const std::wstring_view wordDelimiters) const;
|
||||
|
||||
void _PruneHyperlinks();
|
||||
|
|
|
@ -152,6 +152,10 @@ namespace SettingsModelLocalTests
|
|||
{ "name": "command4", "command": { "action": "splitPane" } },
|
||||
{ "name": "command5", "command": { "action": "splitPane", "split": "auto" } },
|
||||
{ "name": "command6", "command": { "action": "splitPane", "size": 0.25 } },
|
||||
{ "name": "command7", "command": { "action": "splitPane", "split": "right" } },
|
||||
{ "name": "command8", "command": { "action": "splitPane", "split": "left" } },
|
||||
{ "name": "command9", "command": { "action": "splitPane", "split": "up" } },
|
||||
{ "name": "command10", "command": { "action": "splitPane", "split": "down" } },
|
||||
])" };
|
||||
|
||||
const auto commands0Json = VerifyParseSucceeded(commands0String);
|
||||
|
@ -160,7 +164,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(5u, commands.Size());
|
||||
VERIFY_ARE_EQUAL(9u, commands.Size());
|
||||
|
||||
{
|
||||
auto command = commands.Lookup(L"command1");
|
||||
|
@ -170,7 +174,7 @@ namespace SettingsModelLocalTests
|
|||
const auto& realArgs = command.ActionAndArgs().Args().try_as<SplitPaneArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
// Verify the args have the expected value
|
||||
VERIFY_ARE_EQUAL(SplitState::Vertical, realArgs.SplitStyle());
|
||||
VERIFY_ARE_EQUAL(SplitDirection::Right, realArgs.SplitDirection());
|
||||
VERIFY_ARE_EQUAL(0.5, realArgs.SplitSize());
|
||||
}
|
||||
{
|
||||
|
@ -181,7 +185,7 @@ namespace SettingsModelLocalTests
|
|||
const auto& realArgs = command.ActionAndArgs().Args().try_as<SplitPaneArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
// Verify the args have the expected value
|
||||
VERIFY_ARE_EQUAL(SplitState::Horizontal, realArgs.SplitStyle());
|
||||
VERIFY_ARE_EQUAL(SplitDirection::Down, realArgs.SplitDirection());
|
||||
VERIFY_ARE_EQUAL(0.5, realArgs.SplitSize());
|
||||
}
|
||||
{
|
||||
|
@ -192,7 +196,7 @@ namespace SettingsModelLocalTests
|
|||
const auto& realArgs = command.ActionAndArgs().Args().try_as<SplitPaneArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
// Verify the args have the expected value
|
||||
VERIFY_ARE_EQUAL(SplitState::Automatic, realArgs.SplitStyle());
|
||||
VERIFY_ARE_EQUAL(SplitDirection::Automatic, realArgs.SplitDirection());
|
||||
VERIFY_ARE_EQUAL(0.5, realArgs.SplitSize());
|
||||
}
|
||||
{
|
||||
|
@ -203,7 +207,7 @@ namespace SettingsModelLocalTests
|
|||
const auto& realArgs = command.ActionAndArgs().Args().try_as<SplitPaneArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
// Verify the args have the expected value
|
||||
VERIFY_ARE_EQUAL(SplitState::Automatic, realArgs.SplitStyle());
|
||||
VERIFY_ARE_EQUAL(SplitDirection::Automatic, realArgs.SplitDirection());
|
||||
VERIFY_ARE_EQUAL(0.5, realArgs.SplitSize());
|
||||
}
|
||||
{
|
||||
|
@ -214,9 +218,53 @@ namespace SettingsModelLocalTests
|
|||
const auto& realArgs = command.ActionAndArgs().Args().try_as<SplitPaneArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
// Verify the args have the expected value
|
||||
VERIFY_ARE_EQUAL(SplitState::Automatic, realArgs.SplitStyle());
|
||||
VERIFY_ARE_EQUAL(SplitDirection::Automatic, realArgs.SplitDirection());
|
||||
VERIFY_ARE_EQUAL(0.25, realArgs.SplitSize());
|
||||
}
|
||||
{
|
||||
auto command = commands.Lookup(L"command7");
|
||||
VERIFY_IS_NOT_NULL(command);
|
||||
VERIFY_IS_NOT_NULL(command.ActionAndArgs());
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::SplitPane, command.ActionAndArgs().Action());
|
||||
const auto& realArgs = command.ActionAndArgs().Args().try_as<SplitPaneArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
// Verify the args have the expected value
|
||||
VERIFY_ARE_EQUAL(SplitDirection::Right, realArgs.SplitDirection());
|
||||
VERIFY_ARE_EQUAL(0.5, realArgs.SplitSize());
|
||||
}
|
||||
{
|
||||
auto command = commands.Lookup(L"command8");
|
||||
VERIFY_IS_NOT_NULL(command);
|
||||
VERIFY_IS_NOT_NULL(command.ActionAndArgs());
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::SplitPane, command.ActionAndArgs().Action());
|
||||
const auto& realArgs = command.ActionAndArgs().Args().try_as<SplitPaneArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
// Verify the args have the expected value
|
||||
VERIFY_ARE_EQUAL(SplitDirection::Left, realArgs.SplitDirection());
|
||||
VERIFY_ARE_EQUAL(0.5, realArgs.SplitSize());
|
||||
}
|
||||
{
|
||||
auto command = commands.Lookup(L"command9");
|
||||
VERIFY_IS_NOT_NULL(command);
|
||||
VERIFY_IS_NOT_NULL(command.ActionAndArgs());
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::SplitPane, command.ActionAndArgs().Action());
|
||||
const auto& realArgs = command.ActionAndArgs().Args().try_as<SplitPaneArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
// Verify the args have the expected value
|
||||
VERIFY_ARE_EQUAL(SplitDirection::Up, realArgs.SplitDirection());
|
||||
VERIFY_ARE_EQUAL(0.5, realArgs.SplitSize());
|
||||
}
|
||||
{
|
||||
auto command = commands.Lookup(L"command10");
|
||||
VERIFY_IS_NOT_NULL(command);
|
||||
VERIFY_IS_NOT_NULL(command.ActionAndArgs());
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::SplitPane, command.ActionAndArgs().Action());
|
||||
const auto& realArgs = command.ActionAndArgs().Args().try_as<SplitPaneArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
// Verify the args have the expected value
|
||||
VERIFY_ARE_EQUAL(SplitDirection::Down, realArgs.SplitDirection());
|
||||
VERIFY_ARE_EQUAL(0.5, realArgs.SplitSize());
|
||||
}
|
||||
}
|
||||
|
||||
void CommandTests::TestSplitPaneBadSize()
|
||||
|
@ -244,7 +292,7 @@ namespace SettingsModelLocalTests
|
|||
const auto& realArgs = command.ActionAndArgs().Args().try_as<SplitPaneArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
// Verify the args have the expected value
|
||||
VERIFY_ARE_EQUAL(SplitState::Automatic, realArgs.SplitStyle());
|
||||
VERIFY_ARE_EQUAL(SplitDirection::Automatic, realArgs.SplitDirection());
|
||||
VERIFY_ARE_EQUAL(0.25, realArgs.SplitSize());
|
||||
}
|
||||
}
|
||||
|
@ -286,8 +334,10 @@ namespace SettingsModelLocalTests
|
|||
|
||||
const std::string commands0String{ R"([
|
||||
{ "command": { "action": "splitPane", "split": null } },
|
||||
{ "command": { "action": "splitPane", "split": "vertical" } },
|
||||
{ "command": { "action": "splitPane", "split": "horizontal" } },
|
||||
{ "command": { "action": "splitPane", "split": "left" } },
|
||||
{ "command": { "action": "splitPane", "split": "right" } },
|
||||
{ "command": { "action": "splitPane", "split": "up" } },
|
||||
{ "command": { "action": "splitPane", "split": "down" } },
|
||||
{ "command": { "action": "splitPane", "split": "none" } },
|
||||
{ "command": { "action": "splitPane" } },
|
||||
{ "command": { "action": "splitPane", "split": "auto" } },
|
||||
|
@ -301,10 +351,10 @@ namespace SettingsModelLocalTests
|
|||
auto warnings = implementation::Command::LayerJson(commands, commands0Json);
|
||||
VERIFY_ARE_EQUAL(0u, warnings.size());
|
||||
|
||||
// There are only 3 commands here: all of the `"none"`, `"auto"`,
|
||||
// There are only 5 commands here: all of the `"none"`, `"auto"`,
|
||||
// `"foo"`, `null`, and <no args> bindings all generate the same action,
|
||||
// which will generate just a single name for all of them.
|
||||
VERIFY_ARE_EQUAL(3u, commands.Size());
|
||||
VERIFY_ARE_EQUAL(5u, commands.Size());
|
||||
|
||||
{
|
||||
auto command = commands.Lookup(L"Split pane");
|
||||
|
@ -314,27 +364,47 @@ namespace SettingsModelLocalTests
|
|||
const auto& realArgs = command.ActionAndArgs().Args().try_as<SplitPaneArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
// Verify the args have the expected value
|
||||
VERIFY_ARE_EQUAL(SplitState::Automatic, realArgs.SplitStyle());
|
||||
VERIFY_ARE_EQUAL(SplitDirection::Automatic, realArgs.SplitDirection());
|
||||
}
|
||||
{
|
||||
auto command = commands.Lookup(L"Split pane, split: vertical");
|
||||
auto command = commands.Lookup(L"Split pane, split: left");
|
||||
VERIFY_IS_NOT_NULL(command);
|
||||
VERIFY_IS_NOT_NULL(command.ActionAndArgs());
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::SplitPane, command.ActionAndArgs().Action());
|
||||
const auto& realArgs = command.ActionAndArgs().Args().try_as<SplitPaneArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
// Verify the args have the expected value
|
||||
VERIFY_ARE_EQUAL(SplitState::Vertical, realArgs.SplitStyle());
|
||||
VERIFY_ARE_EQUAL(SplitDirection::Left, realArgs.SplitDirection());
|
||||
}
|
||||
{
|
||||
auto command = commands.Lookup(L"Split pane, split: horizontal");
|
||||
auto command = commands.Lookup(L"Split pane, split: right");
|
||||
VERIFY_IS_NOT_NULL(command);
|
||||
VERIFY_IS_NOT_NULL(command.ActionAndArgs());
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::SplitPane, command.ActionAndArgs().Action());
|
||||
const auto& realArgs = command.ActionAndArgs().Args().try_as<SplitPaneArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
// Verify the args have the expected value
|
||||
VERIFY_ARE_EQUAL(SplitState::Horizontal, realArgs.SplitStyle());
|
||||
VERIFY_ARE_EQUAL(SplitDirection::Right, realArgs.SplitDirection());
|
||||
}
|
||||
{
|
||||
auto command = commands.Lookup(L"Split pane, split: up");
|
||||
VERIFY_IS_NOT_NULL(command);
|
||||
VERIFY_IS_NOT_NULL(command.ActionAndArgs());
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::SplitPane, command.ActionAndArgs().Action());
|
||||
const auto& realArgs = command.ActionAndArgs().Args().try_as<SplitPaneArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
// Verify the args have the expected value
|
||||
VERIFY_ARE_EQUAL(SplitDirection::Up, realArgs.SplitDirection());
|
||||
}
|
||||
{
|
||||
auto command = commands.Lookup(L"Split pane, split: down");
|
||||
VERIFY_IS_NOT_NULL(command);
|
||||
VERIFY_IS_NOT_NULL(command.ActionAndArgs());
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::SplitPane, command.ActionAndArgs().Action());
|
||||
const auto& realArgs = command.ActionAndArgs().Args().try_as<SplitPaneArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
// Verify the args have the expected value
|
||||
VERIFY_ARE_EQUAL(SplitDirection::Down, realArgs.SplitDirection());
|
||||
}
|
||||
}
|
||||
void CommandTests::TestLayerOnAutogeneratedName()
|
||||
|
@ -360,7 +430,7 @@ namespace SettingsModelLocalTests
|
|||
const auto& realArgs = command.ActionAndArgs().Args().try_as<SplitPaneArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
// Verify the args have the expected value
|
||||
VERIFY_ARE_EQUAL(SplitState::Vertical, realArgs.SplitStyle());
|
||||
VERIFY_ARE_EQUAL(SplitDirection::Right, realArgs.SplitDirection());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2130,7 +2130,7 @@ namespace SettingsModelLocalTests
|
|||
const auto& realArgs = actionAndArgs.Args().try_as<SplitPaneArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
// Verify the args have the expected value
|
||||
VERIFY_ARE_EQUAL(SplitState::Vertical, realArgs.SplitStyle());
|
||||
VERIFY_ARE_EQUAL(SplitDirection::Right, realArgs.SplitDirection());
|
||||
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
|
||||
VERIFY_IS_TRUE(realArgs.TerminalArgs().Commandline().empty());
|
||||
VERIFY_IS_TRUE(realArgs.TerminalArgs().StartingDirectory().empty());
|
||||
|
@ -2147,7 +2147,7 @@ namespace SettingsModelLocalTests
|
|||
const auto& realArgs = actionAndArgs.Args().try_as<SplitPaneArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
// Verify the args have the expected value
|
||||
VERIFY_ARE_EQUAL(SplitState::Vertical, realArgs.SplitStyle());
|
||||
VERIFY_ARE_EQUAL(SplitDirection::Right, realArgs.SplitDirection());
|
||||
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
|
||||
VERIFY_IS_TRUE(realArgs.TerminalArgs().Commandline().empty());
|
||||
VERIFY_IS_TRUE(realArgs.TerminalArgs().StartingDirectory().empty());
|
||||
|
@ -2161,7 +2161,7 @@ namespace SettingsModelLocalTests
|
|||
const auto& realArgs = actionAndArgs.Args().try_as<SplitPaneArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
// Verify the args have the expected value
|
||||
VERIFY_ARE_EQUAL(SplitState::Vertical, realArgs.SplitStyle());
|
||||
VERIFY_ARE_EQUAL(SplitDirection::Right, realArgs.SplitDirection());
|
||||
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
|
||||
VERIFY_IS_TRUE(realArgs.TerminalArgs().Commandline().empty());
|
||||
VERIFY_IS_TRUE(realArgs.TerminalArgs().StartingDirectory().empty());
|
||||
|
@ -2175,7 +2175,7 @@ namespace SettingsModelLocalTests
|
|||
const auto& realArgs = actionAndArgs.Args().try_as<SplitPaneArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
// Verify the args have the expected value
|
||||
VERIFY_ARE_EQUAL(SplitState::Horizontal, realArgs.SplitStyle());
|
||||
VERIFY_ARE_EQUAL(SplitDirection::Down, realArgs.SplitDirection());
|
||||
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
|
||||
VERIFY_IS_TRUE(realArgs.TerminalArgs().Commandline().empty());
|
||||
VERIFY_IS_TRUE(realArgs.TerminalArgs().StartingDirectory().empty());
|
||||
|
@ -2189,7 +2189,7 @@ namespace SettingsModelLocalTests
|
|||
const auto& realArgs = actionAndArgs.Args().try_as<SplitPaneArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
// Verify the args have the expected value
|
||||
VERIFY_ARE_EQUAL(SplitState::Horizontal, realArgs.SplitStyle());
|
||||
VERIFY_ARE_EQUAL(SplitDirection::Down, realArgs.SplitDirection());
|
||||
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
|
||||
VERIFY_IS_TRUE(realArgs.TerminalArgs().Commandline().empty());
|
||||
VERIFY_IS_TRUE(realArgs.TerminalArgs().StartingDirectory().empty());
|
||||
|
@ -2218,7 +2218,7 @@ namespace SettingsModelLocalTests
|
|||
const auto& realArgs = actionAndArgs.Args().try_as<SplitPaneArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
// Verify the args have the expected value
|
||||
VERIFY_ARE_EQUAL(SplitState::Vertical, realArgs.SplitStyle());
|
||||
VERIFY_ARE_EQUAL(SplitDirection::Right, realArgs.SplitDirection());
|
||||
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
|
||||
VERIFY_IS_TRUE(realArgs.TerminalArgs().Commandline().empty());
|
||||
VERIFY_IS_TRUE(realArgs.TerminalArgs().StartingDirectory().empty());
|
||||
|
|
|
@ -432,7 +432,7 @@ namespace SettingsModelLocalTests
|
|||
VERIFY_ARE_EQUAL(ShortcutAction::SplitPane, actionAndArgs.Action());
|
||||
const auto& realArgs = actionAndArgs.Args().as<SplitPaneArgs>();
|
||||
// Verify the args have the expected value
|
||||
VERIFY_ARE_EQUAL(SplitState::Vertical, realArgs.SplitStyle());
|
||||
VERIFY_ARE_EQUAL(SplitDirection::Right, realArgs.SplitDirection());
|
||||
}
|
||||
{
|
||||
KeyChord kc{ true, false, false, false, static_cast<int32_t>('E'), 0 };
|
||||
|
@ -440,7 +440,7 @@ namespace SettingsModelLocalTests
|
|||
VERIFY_ARE_EQUAL(ShortcutAction::SplitPane, actionAndArgs.Action());
|
||||
const auto& realArgs = actionAndArgs.Args().as<SplitPaneArgs>();
|
||||
// Verify the args have the expected value
|
||||
VERIFY_ARE_EQUAL(SplitState::Horizontal, realArgs.SplitStyle());
|
||||
VERIFY_ARE_EQUAL(SplitDirection::Down, realArgs.SplitDirection());
|
||||
}
|
||||
{
|
||||
KeyChord kc{ true, false, false, false, static_cast<int32_t>('G'), 0 };
|
||||
|
@ -448,7 +448,7 @@ namespace SettingsModelLocalTests
|
|||
VERIFY_ARE_EQUAL(ShortcutAction::SplitPane, actionAndArgs.Action());
|
||||
const auto& realArgs = actionAndArgs.Args().as<SplitPaneArgs>();
|
||||
// Verify the args have the expected value
|
||||
VERIFY_ARE_EQUAL(SplitState::Automatic, realArgs.SplitStyle());
|
||||
VERIFY_ARE_EQUAL(SplitDirection::Automatic, realArgs.SplitDirection());
|
||||
}
|
||||
{
|
||||
KeyChord kc{ true, false, false, false, static_cast<int32_t>('H'), 0 };
|
||||
|
@ -456,7 +456,7 @@ namespace SettingsModelLocalTests
|
|||
VERIFY_ARE_EQUAL(ShortcutAction::SplitPane, actionAndArgs.Action());
|
||||
const auto& realArgs = actionAndArgs.Args().as<SplitPaneArgs>();
|
||||
// Verify the args have the expected value
|
||||
VERIFY_ARE_EQUAL(SplitState::Automatic, realArgs.SplitStyle());
|
||||
VERIFY_ARE_EQUAL(SplitDirection::Automatic, realArgs.SplitDirection());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -256,10 +256,14 @@ namespace SettingsModelLocalTests
|
|||
])" };
|
||||
|
||||
// complex command with key chords
|
||||
const std::string actionsString4{ R"([
|
||||
const std::string actionsString4A{ R"([
|
||||
{ "command": { "action": "adjustFontSize", "delta": 1 }, "keys": "ctrl+c" },
|
||||
{ "command": { "action": "adjustFontSize", "delta": 1 }, "keys": "ctrl+d" }
|
||||
])" };
|
||||
const std::string actionsString4B{ R"([
|
||||
{ "command": { "action": "findMatch", "direction": "next" }, "keys": "ctrl+shift+s" },
|
||||
{ "command": { "action": "findMatch", "direction": "prev" }, "keys": "ctrl+shift+r" }
|
||||
])" };
|
||||
|
||||
// command with name and icon and multiple key chords
|
||||
const std::string actionsString5{ R"([
|
||||
|
@ -372,7 +376,8 @@ namespace SettingsModelLocalTests
|
|||
RoundtripTest<implementation::ActionMap>(actionsString3);
|
||||
|
||||
Log::Comment(L"complex commands with key chords");
|
||||
RoundtripTest<implementation::ActionMap>(actionsString4);
|
||||
RoundtripTest<implementation::ActionMap>(actionsString4A);
|
||||
RoundtripTest<implementation::ActionMap>(actionsString4B);
|
||||
|
||||
Log::Comment(L"command with name and icon and multiple key chords");
|
||||
RoundtripTest<implementation::ActionMap>(actionsString5);
|
||||
|
|
|
@ -124,7 +124,7 @@ namespace SettingsModelLocalTests
|
|||
const auto& realArgs = actionAndArgs.Args().try_as<SplitPaneArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
// Verify the args have the expected value
|
||||
VERIFY_ARE_EQUAL(SplitState::Vertical, realArgs.SplitStyle());
|
||||
VERIFY_ARE_EQUAL(SplitDirection::Right, realArgs.SplitDirection());
|
||||
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
|
||||
VERIFY_IS_TRUE(realArgs.TerminalArgs().Commandline().empty());
|
||||
VERIFY_IS_TRUE(realArgs.TerminalArgs().StartingDirectory().empty());
|
||||
|
@ -145,7 +145,7 @@ namespace SettingsModelLocalTests
|
|||
const auto& realArgs = actionAndArgs.Args().try_as<SplitPaneArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
// Verify the args have the expected value
|
||||
VERIFY_ARE_EQUAL(SplitState::Vertical, realArgs.SplitStyle());
|
||||
VERIFY_ARE_EQUAL(SplitDirection::Right, realArgs.SplitDirection());
|
||||
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
|
||||
VERIFY_IS_TRUE(realArgs.TerminalArgs().Commandline().empty());
|
||||
VERIFY_IS_TRUE(realArgs.TerminalArgs().StartingDirectory().empty());
|
||||
|
@ -167,7 +167,7 @@ namespace SettingsModelLocalTests
|
|||
const auto& realArgs = actionAndArgs.Args().try_as<SplitPaneArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
// Verify the args have the expected value
|
||||
VERIFY_ARE_EQUAL(SplitState::Vertical, realArgs.SplitStyle());
|
||||
VERIFY_ARE_EQUAL(SplitDirection::Right, realArgs.SplitDirection());
|
||||
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
|
||||
VERIFY_IS_TRUE(realArgs.TerminalArgs().Commandline().empty());
|
||||
VERIFY_IS_TRUE(realArgs.TerminalArgs().StartingDirectory().empty());
|
||||
|
@ -189,7 +189,7 @@ namespace SettingsModelLocalTests
|
|||
const auto& realArgs = actionAndArgs.Args().try_as<SplitPaneArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
// Verify the args have the expected value
|
||||
VERIFY_ARE_EQUAL(SplitState::Vertical, realArgs.SplitStyle());
|
||||
VERIFY_ARE_EQUAL(SplitDirection::Right, realArgs.SplitDirection());
|
||||
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
|
||||
VERIFY_IS_TRUE(realArgs.TerminalArgs().Commandline().empty());
|
||||
VERIFY_IS_TRUE(realArgs.TerminalArgs().StartingDirectory().empty());
|
||||
|
@ -211,7 +211,7 @@ namespace SettingsModelLocalTests
|
|||
const auto& realArgs = actionAndArgs.Args().try_as<SplitPaneArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
// Verify the args have the expected value
|
||||
VERIFY_ARE_EQUAL(SplitState::Horizontal, realArgs.SplitStyle());
|
||||
VERIFY_ARE_EQUAL(SplitDirection::Down, realArgs.SplitDirection());
|
||||
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
|
||||
VERIFY_IS_FALSE(realArgs.TerminalArgs().Commandline().empty());
|
||||
VERIFY_IS_TRUE(realArgs.TerminalArgs().StartingDirectory().empty());
|
||||
|
@ -242,7 +242,7 @@ namespace SettingsModelLocalTests
|
|||
const auto& realArgs = actionAndArgs.Args().try_as<SplitPaneArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
// Verify the args have the expected value
|
||||
VERIFY_ARE_EQUAL(SplitState::Horizontal, realArgs.SplitStyle());
|
||||
VERIFY_ARE_EQUAL(SplitDirection::Down, realArgs.SplitDirection());
|
||||
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
|
||||
VERIFY_IS_FALSE(realArgs.TerminalArgs().Commandline().empty());
|
||||
VERIFY_IS_TRUE(realArgs.TerminalArgs().StartingDirectory().empty());
|
||||
|
|
|
@ -715,7 +715,7 @@ namespace TerminalAppLocalTests
|
|||
VERIFY_IS_NOT_NULL(actionAndArgs.Args());
|
||||
auto myArgs = actionAndArgs.Args().try_as<SplitPaneArgs>();
|
||||
VERIFY_IS_NOT_NULL(myArgs);
|
||||
VERIFY_ARE_EQUAL(SplitState::Automatic, myArgs.SplitStyle());
|
||||
VERIFY_ARE_EQUAL(SplitDirection::Automatic, myArgs.SplitDirection());
|
||||
VERIFY_ARE_EQUAL(SplitType::Manual, myArgs.SplitMode());
|
||||
VERIFY_IS_NOT_NULL(myArgs.TerminalArgs());
|
||||
}
|
||||
|
@ -735,7 +735,7 @@ namespace TerminalAppLocalTests
|
|||
VERIFY_IS_NOT_NULL(actionAndArgs.Args());
|
||||
auto myArgs = actionAndArgs.Args().try_as<SplitPaneArgs>();
|
||||
VERIFY_IS_NOT_NULL(myArgs);
|
||||
VERIFY_ARE_EQUAL(SplitState::Horizontal, myArgs.SplitStyle());
|
||||
VERIFY_ARE_EQUAL(SplitDirection::Down, myArgs.SplitDirection());
|
||||
VERIFY_ARE_EQUAL(SplitType::Manual, myArgs.SplitMode());
|
||||
VERIFY_IS_NOT_NULL(myArgs.TerminalArgs());
|
||||
}
|
||||
|
@ -757,7 +757,7 @@ namespace TerminalAppLocalTests
|
|||
VERIFY_IS_NOT_NULL(actionAndArgs.Args());
|
||||
auto myArgs = actionAndArgs.Args().try_as<SplitPaneArgs>();
|
||||
VERIFY_IS_NOT_NULL(myArgs);
|
||||
VERIFY_ARE_EQUAL(SplitState::Vertical, myArgs.SplitStyle());
|
||||
VERIFY_ARE_EQUAL(SplitDirection::Right, myArgs.SplitDirection());
|
||||
VERIFY_ARE_EQUAL(SplitType::Manual, myArgs.SplitMode());
|
||||
VERIFY_IS_NOT_NULL(myArgs.TerminalArgs());
|
||||
}
|
||||
|
@ -799,7 +799,7 @@ namespace TerminalAppLocalTests
|
|||
VERIFY_IS_NOT_NULL(actionAndArgs.Args());
|
||||
auto myArgs = actionAndArgs.Args().try_as<SplitPaneArgs>();
|
||||
VERIFY_IS_NOT_NULL(myArgs);
|
||||
VERIFY_ARE_EQUAL(SplitState::Automatic, myArgs.SplitStyle());
|
||||
VERIFY_ARE_EQUAL(SplitDirection::Automatic, myArgs.SplitDirection());
|
||||
VERIFY_IS_NOT_NULL(myArgs.TerminalArgs());
|
||||
VERIFY_IS_FALSE(myArgs.TerminalArgs().Commandline().empty());
|
||||
VERIFY_IS_TRUE(myArgs.TerminalArgs().StartingDirectory().empty());
|
||||
|
@ -828,7 +828,7 @@ namespace TerminalAppLocalTests
|
|||
VERIFY_IS_NOT_NULL(actionAndArgs.Args());
|
||||
auto myArgs = actionAndArgs.Args().try_as<SplitPaneArgs>();
|
||||
VERIFY_IS_NOT_NULL(myArgs);
|
||||
VERIFY_ARE_EQUAL(SplitState::Horizontal, myArgs.SplitStyle());
|
||||
VERIFY_ARE_EQUAL(SplitDirection::Down, myArgs.SplitDirection());
|
||||
VERIFY_IS_NOT_NULL(myArgs.TerminalArgs());
|
||||
VERIFY_IS_FALSE(myArgs.TerminalArgs().Commandline().empty());
|
||||
VERIFY_IS_TRUE(myArgs.TerminalArgs().StartingDirectory().empty());
|
||||
|
@ -857,7 +857,7 @@ namespace TerminalAppLocalTests
|
|||
VERIFY_IS_NOT_NULL(actionAndArgs.Args());
|
||||
auto myArgs = actionAndArgs.Args().try_as<SplitPaneArgs>();
|
||||
VERIFY_IS_NOT_NULL(myArgs);
|
||||
VERIFY_ARE_EQUAL(SplitState::Automatic, myArgs.SplitStyle());
|
||||
VERIFY_ARE_EQUAL(SplitDirection::Automatic, myArgs.SplitDirection());
|
||||
VERIFY_IS_NOT_NULL(myArgs.TerminalArgs());
|
||||
VERIFY_IS_FALSE(myArgs.TerminalArgs().Commandline().empty());
|
||||
VERIFY_IS_TRUE(myArgs.TerminalArgs().StartingDirectory().empty());
|
||||
|
@ -1779,7 +1779,7 @@ namespace TerminalAppLocalTests
|
|||
VERIFY_IS_NOT_NULL(actionAndArgs.Args());
|
||||
auto myArgs = actionAndArgs.Args().try_as<SplitPaneArgs>();
|
||||
VERIFY_IS_NOT_NULL(myArgs);
|
||||
VERIFY_ARE_EQUAL(SplitState::Automatic, myArgs.SplitStyle());
|
||||
VERIFY_ARE_EQUAL(SplitDirection::Automatic, myArgs.SplitDirection());
|
||||
VERIFY_ARE_EQUAL(0.5f, myArgs.SplitSize());
|
||||
VERIFY_IS_NOT_NULL(myArgs.TerminalArgs());
|
||||
}
|
||||
|
@ -1799,7 +1799,7 @@ namespace TerminalAppLocalTests
|
|||
VERIFY_IS_NOT_NULL(actionAndArgs.Args());
|
||||
auto myArgs = actionAndArgs.Args().try_as<SplitPaneArgs>();
|
||||
VERIFY_IS_NOT_NULL(myArgs);
|
||||
VERIFY_ARE_EQUAL(SplitState::Automatic, myArgs.SplitStyle());
|
||||
VERIFY_ARE_EQUAL(SplitDirection::Automatic, myArgs.SplitDirection());
|
||||
VERIFY_ARE_EQUAL(0.3f, myArgs.SplitSize());
|
||||
VERIFY_IS_NOT_NULL(myArgs.TerminalArgs());
|
||||
}
|
||||
|
@ -1820,7 +1820,7 @@ namespace TerminalAppLocalTests
|
|||
VERIFY_IS_NOT_NULL(actionAndArgs.Args());
|
||||
auto myArgs = actionAndArgs.Args().try_as<SplitPaneArgs>();
|
||||
VERIFY_IS_NOT_NULL(myArgs);
|
||||
VERIFY_ARE_EQUAL(SplitState::Automatic, myArgs.SplitStyle());
|
||||
VERIFY_ARE_EQUAL(SplitDirection::Automatic, myArgs.SplitDirection());
|
||||
VERIFY_ARE_EQUAL(0.3f, myArgs.SplitSize());
|
||||
VERIFY_IS_NOT_NULL(myArgs.TerminalArgs());
|
||||
}
|
||||
|
@ -1830,7 +1830,7 @@ namespace TerminalAppLocalTests
|
|||
VERIFY_IS_NOT_NULL(actionAndArgs.Args());
|
||||
auto myArgs = actionAndArgs.Args().try_as<SplitPaneArgs>();
|
||||
VERIFY_IS_NOT_NULL(myArgs);
|
||||
VERIFY_ARE_EQUAL(SplitState::Automatic, myArgs.SplitStyle());
|
||||
VERIFY_ARE_EQUAL(SplitDirection::Automatic, myArgs.SplitDirection());
|
||||
VERIFY_ARE_EQUAL(0.5f, myArgs.SplitSize());
|
||||
VERIFY_IS_NOT_NULL(myArgs.TerminalArgs());
|
||||
}
|
||||
|
@ -1852,7 +1852,7 @@ namespace TerminalAppLocalTests
|
|||
VERIFY_IS_NOT_NULL(actionAndArgs.Args());
|
||||
auto myArgs = actionAndArgs.Args().try_as<SplitPaneArgs>();
|
||||
VERIFY_IS_NOT_NULL(myArgs);
|
||||
VERIFY_ARE_EQUAL(SplitState::Automatic, myArgs.SplitStyle());
|
||||
VERIFY_ARE_EQUAL(SplitDirection::Automatic, myArgs.SplitDirection());
|
||||
VERIFY_ARE_EQUAL(0.3f, myArgs.SplitSize());
|
||||
VERIFY_IS_NOT_NULL(myArgs.TerminalArgs());
|
||||
}
|
||||
|
@ -1862,7 +1862,7 @@ namespace TerminalAppLocalTests
|
|||
VERIFY_IS_NOT_NULL(actionAndArgs.Args());
|
||||
auto myArgs = actionAndArgs.Args().try_as<SplitPaneArgs>();
|
||||
VERIFY_IS_NOT_NULL(myArgs);
|
||||
VERIFY_ARE_EQUAL(SplitState::Automatic, myArgs.SplitStyle());
|
||||
VERIFY_ARE_EQUAL(SplitDirection::Automatic, myArgs.SplitDirection());
|
||||
VERIFY_ARE_EQUAL(0.7f, myArgs.SplitSize());
|
||||
VERIFY_IS_NOT_NULL(myArgs.TerminalArgs());
|
||||
}
|
||||
|
|
|
@ -132,7 +132,7 @@ namespace TerminalAppLocalTests
|
|||
const auto& realArgs = actionAndArgs.Args().try_as<SplitPaneArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
// Verify the args have the expected value
|
||||
VERIFY_ARE_EQUAL(SplitState::Automatic, realArgs.SplitStyle());
|
||||
VERIFY_ARE_EQUAL(SplitDirection::Automatic, realArgs.SplitDirection());
|
||||
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
|
||||
VERIFY_IS_TRUE(realArgs.TerminalArgs().Commandline().empty());
|
||||
VERIFY_IS_TRUE(realArgs.TerminalArgs().StartingDirectory().empty());
|
||||
|
@ -156,7 +156,7 @@ namespace TerminalAppLocalTests
|
|||
const auto& realArgs = actionAndArgs.Args().try_as<SplitPaneArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
// Verify the args have the expected value
|
||||
VERIFY_ARE_EQUAL(SplitState::Automatic, realArgs.SplitStyle());
|
||||
VERIFY_ARE_EQUAL(SplitDirection::Automatic, realArgs.SplitDirection());
|
||||
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
|
||||
VERIFY_IS_TRUE(realArgs.TerminalArgs().Commandline().empty());
|
||||
VERIFY_IS_TRUE(realArgs.TerminalArgs().StartingDirectory().empty());
|
||||
|
@ -174,7 +174,7 @@ namespace TerminalAppLocalTests
|
|||
const auto& realArgs = actionAndArgs.Args().try_as<SplitPaneArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
// Verify the args have the expected value
|
||||
VERIFY_ARE_EQUAL(SplitState::Automatic, realArgs.SplitStyle());
|
||||
VERIFY_ARE_EQUAL(SplitDirection::Automatic, realArgs.SplitDirection());
|
||||
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
|
||||
VERIFY_IS_TRUE(realArgs.TerminalArgs().Commandline().empty());
|
||||
VERIFY_IS_TRUE(realArgs.TerminalArgs().StartingDirectory().empty());
|
||||
|
@ -192,7 +192,7 @@ namespace TerminalAppLocalTests
|
|||
const auto& realArgs = actionAndArgs.Args().try_as<SplitPaneArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
// Verify the args have the expected value
|
||||
VERIFY_ARE_EQUAL(SplitState::Automatic, realArgs.SplitStyle());
|
||||
VERIFY_ARE_EQUAL(SplitDirection::Automatic, realArgs.SplitDirection());
|
||||
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
|
||||
VERIFY_IS_TRUE(realArgs.TerminalArgs().Commandline().empty());
|
||||
VERIFY_IS_TRUE(realArgs.TerminalArgs().StartingDirectory().empty());
|
||||
|
@ -259,7 +259,7 @@ namespace TerminalAppLocalTests
|
|||
const auto& realArgs = actionAndArgs.Args().try_as<SplitPaneArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
// Verify the args have the expected value
|
||||
VERIFY_ARE_EQUAL(SplitState::Automatic, realArgs.SplitStyle());
|
||||
VERIFY_ARE_EQUAL(SplitDirection::Automatic, realArgs.SplitDirection());
|
||||
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
|
||||
VERIFY_IS_TRUE(realArgs.TerminalArgs().Commandline().empty());
|
||||
VERIFY_IS_TRUE(realArgs.TerminalArgs().StartingDirectory().empty());
|
||||
|
@ -283,7 +283,7 @@ namespace TerminalAppLocalTests
|
|||
const auto& realArgs = actionAndArgs.Args().try_as<SplitPaneArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
// Verify the args have the expected value
|
||||
VERIFY_ARE_EQUAL(SplitState::Automatic, realArgs.SplitStyle());
|
||||
VERIFY_ARE_EQUAL(SplitDirection::Automatic, realArgs.SplitDirection());
|
||||
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
|
||||
VERIFY_IS_TRUE(realArgs.TerminalArgs().Commandline().empty());
|
||||
VERIFY_IS_TRUE(realArgs.TerminalArgs().StartingDirectory().empty());
|
||||
|
@ -301,7 +301,7 @@ namespace TerminalAppLocalTests
|
|||
const auto& realArgs = actionAndArgs.Args().try_as<SplitPaneArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
// Verify the args have the expected value
|
||||
VERIFY_ARE_EQUAL(SplitState::Automatic, realArgs.SplitStyle());
|
||||
VERIFY_ARE_EQUAL(SplitDirection::Automatic, realArgs.SplitDirection());
|
||||
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
|
||||
VERIFY_IS_TRUE(realArgs.TerminalArgs().Commandline().empty());
|
||||
VERIFY_IS_TRUE(realArgs.TerminalArgs().StartingDirectory().empty());
|
||||
|
@ -319,7 +319,7 @@ namespace TerminalAppLocalTests
|
|||
const auto& realArgs = actionAndArgs.Args().try_as<SplitPaneArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
// Verify the args have the expected value
|
||||
VERIFY_ARE_EQUAL(SplitState::Automatic, realArgs.SplitStyle());
|
||||
VERIFY_ARE_EQUAL(SplitDirection::Automatic, realArgs.SplitDirection());
|
||||
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
|
||||
VERIFY_IS_TRUE(realArgs.TerminalArgs().Commandline().empty());
|
||||
VERIFY_IS_TRUE(realArgs.TerminalArgs().StartingDirectory().empty());
|
||||
|
@ -388,7 +388,7 @@ namespace TerminalAppLocalTests
|
|||
const auto& realArgs = actionAndArgs.Args().try_as<SplitPaneArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
// Verify the args have the expected value
|
||||
VERIFY_ARE_EQUAL(SplitState::Automatic, realArgs.SplitStyle());
|
||||
VERIFY_ARE_EQUAL(SplitDirection::Automatic, realArgs.SplitDirection());
|
||||
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
|
||||
VERIFY_IS_TRUE(realArgs.TerminalArgs().Commandline().empty());
|
||||
VERIFY_IS_TRUE(realArgs.TerminalArgs().StartingDirectory().empty());
|
||||
|
@ -412,7 +412,7 @@ namespace TerminalAppLocalTests
|
|||
const auto& realArgs = actionAndArgs.Args().try_as<SplitPaneArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
// Verify the args have the expected value
|
||||
VERIFY_ARE_EQUAL(SplitState::Automatic, realArgs.SplitStyle());
|
||||
VERIFY_ARE_EQUAL(SplitDirection::Automatic, realArgs.SplitDirection());
|
||||
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
|
||||
VERIFY_IS_TRUE(realArgs.TerminalArgs().Commandline().empty());
|
||||
VERIFY_IS_TRUE(realArgs.TerminalArgs().StartingDirectory().empty());
|
||||
|
@ -430,7 +430,7 @@ namespace TerminalAppLocalTests
|
|||
const auto& realArgs = actionAndArgs.Args().try_as<SplitPaneArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
// Verify the args have the expected value
|
||||
VERIFY_ARE_EQUAL(SplitState::Automatic, realArgs.SplitStyle());
|
||||
VERIFY_ARE_EQUAL(SplitDirection::Automatic, realArgs.SplitDirection());
|
||||
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
|
||||
VERIFY_IS_TRUE(realArgs.TerminalArgs().Commandline().empty());
|
||||
VERIFY_IS_TRUE(realArgs.TerminalArgs().StartingDirectory().empty());
|
||||
|
@ -448,7 +448,7 @@ namespace TerminalAppLocalTests
|
|||
const auto& realArgs = actionAndArgs.Args().try_as<SplitPaneArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
// Verify the args have the expected value
|
||||
VERIFY_ARE_EQUAL(SplitState::Automatic, realArgs.SplitStyle());
|
||||
VERIFY_ARE_EQUAL(SplitDirection::Automatic, realArgs.SplitDirection());
|
||||
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
|
||||
VERIFY_IS_TRUE(realArgs.TerminalArgs().Commandline().empty());
|
||||
VERIFY_IS_TRUE(realArgs.TerminalArgs().StartingDirectory().empty());
|
||||
|
@ -680,16 +680,16 @@ namespace TerminalAppLocalTests
|
|||
// <Command Palette>
|
||||
// ├─ profile0...
|
||||
// | ├─ Split pane, profile: profile0
|
||||
// | ├─ Split pane, direction: vertical, profile: profile0
|
||||
// | └─ Split pane, direction: horizontal, profile: profile0
|
||||
// | ├─ Split pane, direction: right, profile: profile0
|
||||
// | └─ Split pane, direction: down, profile: profile0
|
||||
// ├─ profile1...
|
||||
// | ├─Split pane, profile: profile1
|
||||
// | ├─Split pane, direction: vertical, profile: profile1
|
||||
// | └─Split pane, direction: horizontal, profile: profile1
|
||||
// | ├─Split pane, direction: right, profile: profile1
|
||||
// | └─Split pane, direction: down, profile: profile1
|
||||
// └─ profile2...
|
||||
// ├─ Split pane, profile: profile2
|
||||
// ├─ Split pane, direction: vertical, profile: profile2
|
||||
// └─ Split pane, direction: horizontal, profile: profile2
|
||||
// ├─ Split pane, direction: right, profile: profile2
|
||||
// └─ Split pane, direction: down, profile: profile2
|
||||
|
||||
const std::string settingsJson{ R"(
|
||||
{
|
||||
|
@ -719,8 +719,8 @@ namespace TerminalAppLocalTests
|
|||
"name": "${profile.name}...",
|
||||
"commands": [
|
||||
{ "command": { "action": "splitPane", "profile": "${profile.name}", "split": "auto" } },
|
||||
{ "command": { "action": "splitPane", "profile": "${profile.name}", "split": "vertical" } },
|
||||
{ "command": { "action": "splitPane", "profile": "${profile.name}", "split": "horizontal" } }
|
||||
{ "command": { "action": "splitPane", "profile": "${profile.name}", "split": "right" } },
|
||||
{ "command": { "action": "splitPane", "profile": "${profile.name}", "split": "down" } }
|
||||
]
|
||||
}
|
||||
],
|
||||
|
@ -762,7 +762,7 @@ namespace TerminalAppLocalTests
|
|||
const auto& realArgs = childActionAndArgs.Args().try_as<SplitPaneArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
// Verify the args have the expected value
|
||||
VERIFY_ARE_EQUAL(SplitState::Automatic, realArgs.SplitStyle());
|
||||
VERIFY_ARE_EQUAL(SplitDirection::Automatic, realArgs.SplitDirection());
|
||||
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
|
||||
VERIFY_IS_TRUE(realArgs.TerminalArgs().Commandline().empty());
|
||||
VERIFY_IS_TRUE(realArgs.TerminalArgs().StartingDirectory().empty());
|
||||
|
@ -773,7 +773,7 @@ namespace TerminalAppLocalTests
|
|||
VERIFY_IS_FALSE(childCommand.HasNestedCommands());
|
||||
}
|
||||
{
|
||||
winrt::hstring childCommandName{ fmt::format(L"Split pane, split: horizontal, profile: {}", name) };
|
||||
winrt::hstring childCommandName{ fmt::format(L"Split pane, split: down, profile: {}", name) };
|
||||
auto childCommand = command.NestedCommands().Lookup(childCommandName);
|
||||
VERIFY_IS_NOT_NULL(childCommand);
|
||||
auto childActionAndArgs = childCommand.ActionAndArgs();
|
||||
|
@ -783,7 +783,7 @@ namespace TerminalAppLocalTests
|
|||
const auto& realArgs = childActionAndArgs.Args().try_as<SplitPaneArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
// Verify the args have the expected value
|
||||
VERIFY_ARE_EQUAL(SplitState::Horizontal, realArgs.SplitStyle());
|
||||
VERIFY_ARE_EQUAL(SplitDirection::Down, realArgs.SplitDirection());
|
||||
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
|
||||
VERIFY_IS_TRUE(realArgs.TerminalArgs().Commandline().empty());
|
||||
VERIFY_IS_TRUE(realArgs.TerminalArgs().StartingDirectory().empty());
|
||||
|
@ -794,7 +794,7 @@ namespace TerminalAppLocalTests
|
|||
VERIFY_IS_FALSE(childCommand.HasNestedCommands());
|
||||
}
|
||||
{
|
||||
winrt::hstring childCommandName{ fmt::format(L"Split pane, split: vertical, profile: {}", name) };
|
||||
winrt::hstring childCommandName{ fmt::format(L"Split pane, split: right, profile: {}", name) };
|
||||
auto childCommand = command.NestedCommands().Lookup(childCommandName);
|
||||
VERIFY_IS_NOT_NULL(childCommand);
|
||||
auto childActionAndArgs = childCommand.ActionAndArgs();
|
||||
|
@ -804,7 +804,7 @@ namespace TerminalAppLocalTests
|
|||
const auto& realArgs = childActionAndArgs.Args().try_as<SplitPaneArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
// Verify the args have the expected value
|
||||
VERIFY_ARE_EQUAL(SplitState::Vertical, realArgs.SplitStyle());
|
||||
VERIFY_ARE_EQUAL(SplitDirection::Right, realArgs.SplitDirection());
|
||||
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
|
||||
VERIFY_IS_TRUE(realArgs.TerminalArgs().Commandline().empty());
|
||||
VERIFY_IS_TRUE(realArgs.TerminalArgs().StartingDirectory().empty());
|
||||
|
@ -915,16 +915,16 @@ namespace TerminalAppLocalTests
|
|||
// └─ New Pane...
|
||||
// ├─ profile0...
|
||||
// | ├─ Split automatically
|
||||
// | ├─ Split vertically
|
||||
// | └─ Split horizontally
|
||||
// | ├─ Split right
|
||||
// | └─ Split down
|
||||
// ├─ profile1...
|
||||
// | ├─ Split automatically
|
||||
// | ├─ Split vertically
|
||||
// | └─ Split horizontally
|
||||
// | ├─ Split right
|
||||
// | └─ Split down
|
||||
// └─ profile2...
|
||||
// ├─ Split automatically
|
||||
// ├─ Split vertically
|
||||
// └─ Split horizontally
|
||||
// ├─ Split right
|
||||
// └─ Split down
|
||||
|
||||
const std::string settingsJson{ R"(
|
||||
{
|
||||
|
@ -957,8 +957,8 @@ namespace TerminalAppLocalTests
|
|||
"name": "${profile.name}...",
|
||||
"commands": [
|
||||
{ "command": { "action": "splitPane", "profile": "${profile.name}", "split": "auto" } },
|
||||
{ "command": { "action": "splitPane", "profile": "${profile.name}", "split": "vertical" } },
|
||||
{ "command": { "action": "splitPane", "profile": "${profile.name}", "split": "horizontal" } }
|
||||
{ "command": { "action": "splitPane", "profile": "${profile.name}", "split": "right" } },
|
||||
{ "command": { "action": "splitPane", "profile": "${profile.name}", "split": "down" } }
|
||||
]
|
||||
}
|
||||
]
|
||||
|
@ -1010,7 +1010,7 @@ namespace TerminalAppLocalTests
|
|||
const auto& realArgs = childActionAndArgs.Args().try_as<SplitPaneArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
// Verify the args have the expected value
|
||||
VERIFY_ARE_EQUAL(SplitState::Automatic, realArgs.SplitStyle());
|
||||
VERIFY_ARE_EQUAL(SplitDirection::Automatic, realArgs.SplitDirection());
|
||||
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
|
||||
VERIFY_IS_TRUE(realArgs.TerminalArgs().Commandline().empty());
|
||||
VERIFY_IS_TRUE(realArgs.TerminalArgs().StartingDirectory().empty());
|
||||
|
@ -1021,7 +1021,7 @@ namespace TerminalAppLocalTests
|
|||
VERIFY_IS_FALSE(childCommand.HasNestedCommands());
|
||||
}
|
||||
{
|
||||
winrt::hstring childCommandName{ fmt::format(L"Split pane, split: horizontal, profile: {}", name) };
|
||||
winrt::hstring childCommandName{ fmt::format(L"Split pane, split: down, profile: {}", name) };
|
||||
auto childCommand = command.NestedCommands().Lookup(childCommandName);
|
||||
VERIFY_IS_NOT_NULL(childCommand);
|
||||
auto childActionAndArgs = childCommand.ActionAndArgs();
|
||||
|
@ -1031,7 +1031,7 @@ namespace TerminalAppLocalTests
|
|||
const auto& realArgs = childActionAndArgs.Args().try_as<SplitPaneArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
// Verify the args have the expected value
|
||||
VERIFY_ARE_EQUAL(SplitState::Horizontal, realArgs.SplitStyle());
|
||||
VERIFY_ARE_EQUAL(SplitDirection::Down, realArgs.SplitDirection());
|
||||
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
|
||||
VERIFY_IS_TRUE(realArgs.TerminalArgs().Commandline().empty());
|
||||
VERIFY_IS_TRUE(realArgs.TerminalArgs().StartingDirectory().empty());
|
||||
|
@ -1042,7 +1042,7 @@ namespace TerminalAppLocalTests
|
|||
VERIFY_IS_FALSE(childCommand.HasNestedCommands());
|
||||
}
|
||||
{
|
||||
winrt::hstring childCommandName{ fmt::format(L"Split pane, split: vertical, profile: {}", name) };
|
||||
winrt::hstring childCommandName{ fmt::format(L"Split pane, split: right, profile: {}", name) };
|
||||
auto childCommand = command.NestedCommands().Lookup(childCommandName);
|
||||
VERIFY_IS_NOT_NULL(childCommand);
|
||||
auto childActionAndArgs = childCommand.ActionAndArgs();
|
||||
|
@ -1052,7 +1052,7 @@ namespace TerminalAppLocalTests
|
|||
const auto& realArgs = childActionAndArgs.Args().try_as<SplitPaneArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
// Verify the args have the expected value
|
||||
VERIFY_ARE_EQUAL(SplitState::Vertical, realArgs.SplitStyle());
|
||||
VERIFY_ARE_EQUAL(SplitDirection::Right, realArgs.SplitDirection());
|
||||
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
|
||||
VERIFY_IS_TRUE(realArgs.TerminalArgs().Commandline().empty());
|
||||
VERIFY_IS_TRUE(realArgs.TerminalArgs().StartingDirectory().empty());
|
||||
|
@ -1127,7 +1127,7 @@ namespace TerminalAppLocalTests
|
|||
const auto& realArgs = actionAndArgs.Args().try_as<SplitPaneArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
// Verify the args have the expected value
|
||||
VERIFY_ARE_EQUAL(SplitState::Automatic, realArgs.SplitStyle());
|
||||
VERIFY_ARE_EQUAL(SplitDirection::Automatic, realArgs.SplitDirection());
|
||||
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
|
||||
VERIFY_IS_TRUE(realArgs.TerminalArgs().Commandline().empty());
|
||||
VERIFY_IS_TRUE(realArgs.TerminalArgs().StartingDirectory().empty());
|
||||
|
@ -1156,7 +1156,7 @@ namespace TerminalAppLocalTests
|
|||
const auto& realArgs = actionAndArgs.Args().try_as<SplitPaneArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
// Verify the args have the expected value
|
||||
VERIFY_ARE_EQUAL(SplitState::Automatic, realArgs.SplitStyle());
|
||||
VERIFY_ARE_EQUAL(SplitDirection::Automatic, realArgs.SplitDirection());
|
||||
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
|
||||
VERIFY_IS_TRUE(realArgs.TerminalArgs().Commandline().empty());
|
||||
VERIFY_IS_TRUE(realArgs.TerminalArgs().StartingDirectory().empty());
|
||||
|
@ -1174,7 +1174,7 @@ namespace TerminalAppLocalTests
|
|||
const auto& realArgs = actionAndArgs.Args().try_as<SplitPaneArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
// Verify the args have the expected value
|
||||
VERIFY_ARE_EQUAL(SplitState::Automatic, realArgs.SplitStyle());
|
||||
VERIFY_ARE_EQUAL(SplitDirection::Automatic, realArgs.SplitDirection());
|
||||
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
|
||||
VERIFY_IS_TRUE(realArgs.TerminalArgs().Commandline().empty());
|
||||
VERIFY_IS_TRUE(realArgs.TerminalArgs().StartingDirectory().empty());
|
||||
|
@ -1192,7 +1192,7 @@ namespace TerminalAppLocalTests
|
|||
const auto& realArgs = actionAndArgs.Args().try_as<SplitPaneArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
// Verify the args have the expected value
|
||||
VERIFY_ARE_EQUAL(SplitState::Automatic, realArgs.SplitStyle());
|
||||
VERIFY_ARE_EQUAL(SplitDirection::Automatic, realArgs.SplitDirection());
|
||||
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
|
||||
VERIFY_IS_TRUE(realArgs.TerminalArgs().Commandline().empty());
|
||||
VERIFY_IS_TRUE(realArgs.TerminalArgs().StartingDirectory().empty());
|
||||
|
|
|
@ -508,7 +508,7 @@ namespace TerminalAppLocalTests
|
|||
|
||||
Log::Comment(NoThrowString().Format(L"Duplicate the first pane"));
|
||||
result = RunOnUIThread([&page]() {
|
||||
page->_SplitPane(SplitState::Automatic, SplitType::Duplicate, 0.5f, nullptr);
|
||||
page->_SplitPane(SplitDirection::Automatic, SplitType::Duplicate, 0.5f, nullptr);
|
||||
|
||||
VERIFY_ARE_EQUAL(1u, page->_tabs.Size());
|
||||
auto tab = page->_GetTerminalTabImpl(page->_tabs.GetAt(0));
|
||||
|
@ -526,7 +526,7 @@ namespace TerminalAppLocalTests
|
|||
|
||||
Log::Comment(NoThrowString().Format(L"Duplicate the pane, and don't crash"));
|
||||
result = RunOnUIThread([&page]() {
|
||||
page->_SplitPane(SplitState::Automatic, SplitType::Duplicate, 0.5f, nullptr);
|
||||
page->_SplitPane(SplitDirection::Automatic, SplitType::Duplicate, 0.5f, nullptr);
|
||||
|
||||
VERIFY_ARE_EQUAL(1u, page->_tabs.Size());
|
||||
auto tab = page->_GetTerminalTabImpl(page->_tabs.GetAt(0));
|
||||
|
@ -844,7 +844,7 @@ namespace TerminalAppLocalTests
|
|||
// | 1 | 2 |
|
||||
// | | |
|
||||
// -------------------
|
||||
page->_SplitPane(SplitState::Vertical, SplitType::Duplicate, 0.5f, nullptr);
|
||||
page->_SplitPane(SplitDirection::Right, SplitType::Duplicate, 0.5f, nullptr);
|
||||
secondId = tab->_activePane->Id().value();
|
||||
});
|
||||
Sleep(250);
|
||||
|
@ -862,7 +862,7 @@ namespace TerminalAppLocalTests
|
|||
// | 3 | |
|
||||
// | | |
|
||||
// -------------------
|
||||
page->_SplitPane(SplitState::Horizontal, SplitType::Duplicate, 0.5f, nullptr);
|
||||
page->_SplitPane(SplitDirection::Down, SplitType::Duplicate, 0.5f, nullptr);
|
||||
auto tab = page->_GetTerminalTabImpl(page->_tabs.GetAt(0));
|
||||
// Split again to make the 3rd tab
|
||||
thirdId = tab->_activePane->Id().value();
|
||||
|
@ -882,7 +882,7 @@ namespace TerminalAppLocalTests
|
|||
// | 3 | 4 |
|
||||
// | | |
|
||||
// -------------------
|
||||
page->_SplitPane(SplitState::Horizontal, SplitType::Duplicate, 0.5f, nullptr);
|
||||
page->_SplitPane(SplitDirection::Down, SplitType::Duplicate, 0.5f, nullptr);
|
||||
auto tab = page->_GetTerminalTabImpl(page->_tabs.GetAt(0));
|
||||
fourthId = tab->_activePane->Id().value();
|
||||
});
|
||||
|
|
|
@ -80,8 +80,8 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
|
|||
peasant.IdentifyWindowsRequested({ this, &Monarch::_identifyWindows });
|
||||
peasant.RenameRequested({ this, &Monarch::_renameRequested });
|
||||
|
||||
peasant.ShowTrayIconRequested([this](auto&&, auto&&) { _ShowTrayIconRequestedHandlers(*this, nullptr); });
|
||||
peasant.HideTrayIconRequested([this](auto&&, auto&&) { _HideTrayIconRequestedHandlers(*this, nullptr); });
|
||||
peasant.ShowNotificationIconRequested([this](auto&&, auto&&) { _ShowNotificationIconRequestedHandlers(*this, nullptr); });
|
||||
peasant.HideNotificationIconRequested([this](auto&&, auto&&) { _HideNotificationIconRequestedHandlers(*this, nullptr); });
|
||||
peasant.QuitAllRequested({ this, &Monarch::_handleQuitAll });
|
||||
|
||||
_peasants[newPeasantsId] = peasant;
|
||||
|
@ -147,6 +147,7 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
|
|||
// - <none>
|
||||
void Monarch::SignalClose(const uint64_t peasantId)
|
||||
{
|
||||
_clearOldMruEntries(peasantId);
|
||||
_peasants.erase(peasantId);
|
||||
_WindowClosedHandlers(nullptr, nullptr);
|
||||
}
|
||||
|
|
|
@ -60,8 +60,8 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
|
|||
Windows::Foundation::Collections::IVectorView<winrt::Microsoft::Terminal::Remoting::PeasantInfo> GetPeasantInfos();
|
||||
|
||||
TYPED_EVENT(FindTargetWindowRequested, winrt::Windows::Foundation::IInspectable, winrt::Microsoft::Terminal::Remoting::FindTargetWindowArgs);
|
||||
TYPED_EVENT(ShowTrayIconRequested, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
|
||||
TYPED_EVENT(HideTrayIconRequested, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
|
||||
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);
|
||||
|
|
|
@ -54,8 +54,8 @@ namespace Microsoft.Terminal.Remoting
|
|||
Windows.Foundation.Collections.IVectorView<PeasantInfo> GetPeasantInfos { get; };
|
||||
|
||||
event Windows.Foundation.TypedEventHandler<Object, FindTargetWindowArgs> FindTargetWindowRequested;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> ShowTrayIconRequested;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> HideTrayIconRequested;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> ShowNotificationIconRequested;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> HideNotificationIconRequested;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> WindowCreated;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> WindowClosed;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> QuitAllRequested;
|
||||
|
|
|
@ -226,34 +226,34 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
|
|||
TraceLoggingKeyword(TIL_KEYWORD_TRACE));
|
||||
}
|
||||
|
||||
void Peasant::RequestShowTrayIcon()
|
||||
void Peasant::RequestShowNotificationIcon()
|
||||
{
|
||||
try
|
||||
{
|
||||
_ShowTrayIconRequestedHandlers(*this, nullptr);
|
||||
_ShowNotificationIconRequestedHandlers(*this, nullptr);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
LOG_CAUGHT_EXCEPTION();
|
||||
}
|
||||
TraceLoggingWrite(g_hRemotingProvider,
|
||||
"Peasant_RequestShowTrayIcon",
|
||||
"Peasant_RequestShowNotificationIcon",
|
||||
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE),
|
||||
TraceLoggingKeyword(TIL_KEYWORD_TRACE));
|
||||
}
|
||||
|
||||
void Peasant::RequestHideTrayIcon()
|
||||
void Peasant::RequestHideNotificationIcon()
|
||||
{
|
||||
try
|
||||
{
|
||||
_HideTrayIconRequestedHandlers(*this, nullptr);
|
||||
_HideNotificationIconRequestedHandlers(*this, nullptr);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
LOG_CAUGHT_EXCEPTION();
|
||||
}
|
||||
TraceLoggingWrite(g_hRemotingProvider,
|
||||
"Peasant_RequestHideTrayIcon",
|
||||
"Peasant_RequestHideNotificationIcon",
|
||||
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE),
|
||||
TraceLoggingKeyword(TIL_KEYWORD_TRACE));
|
||||
}
|
||||
|
|
|
@ -28,8 +28,8 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
|
|||
void RequestIdentifyWindows();
|
||||
void DisplayWindowId();
|
||||
void RequestRename(const winrt::Microsoft::Terminal::Remoting::RenameRequestArgs& args);
|
||||
void RequestShowTrayIcon();
|
||||
void RequestHideTrayIcon();
|
||||
void RequestShowNotificationIcon();
|
||||
void RequestHideNotificationIcon();
|
||||
void RequestQuitAll();
|
||||
void Quit();
|
||||
|
||||
|
@ -45,8 +45,8 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
|
|||
TYPED_EVENT(DisplayWindowIdRequested, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
|
||||
TYPED_EVENT(RenameRequested, winrt::Windows::Foundation::IInspectable, winrt::Microsoft::Terminal::Remoting::RenameRequestArgs);
|
||||
TYPED_EVENT(SummonRequested, winrt::Windows::Foundation::IInspectable, winrt::Microsoft::Terminal::Remoting::SummonWindowBehavior);
|
||||
TYPED_EVENT(ShowTrayIconRequested, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
|
||||
TYPED_EVENT(HideTrayIconRequested, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
|
||||
TYPED_EVENT(ShowNotificationIconRequested, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
|
||||
TYPED_EVENT(HideNotificationIconRequested, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
|
||||
TYPED_EVENT(QuitAllRequested, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
|
||||
TYPED_EVENT(QuitRequested, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
|
||||
|
||||
|
|
|
@ -65,8 +65,8 @@ namespace Microsoft.Terminal.Remoting
|
|||
void RequestIdentifyWindows(); // Tells us to raise a IdentifyWindowsRequested
|
||||
void RequestRename(RenameRequestArgs args); // Tells us to raise a RenameRequested
|
||||
void Summon(SummonWindowBehavior behavior);
|
||||
void RequestShowTrayIcon();
|
||||
void RequestHideTrayIcon();
|
||||
void RequestShowNotificationIcon();
|
||||
void RequestHideNotificationIcon();
|
||||
void RequestQuitAll();
|
||||
void Quit();
|
||||
|
||||
|
@ -76,8 +76,8 @@ namespace Microsoft.Terminal.Remoting
|
|||
event Windows.Foundation.TypedEventHandler<Object, Object> DisplayWindowIdRequested;
|
||||
event Windows.Foundation.TypedEventHandler<Object, RenameRequestArgs> RenameRequested;
|
||||
event Windows.Foundation.TypedEventHandler<Object, SummonWindowBehavior> SummonRequested;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> ShowTrayIconRequested;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> HideTrayIconRequested;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> ShowNotificationIconRequested;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> HideNotificationIconRequested;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> QuitAllRequested;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> QuitRequested;
|
||||
};
|
||||
|
|
|
@ -269,8 +269,8 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
|
|||
_monarch.WindowCreated({ get_weak(), &WindowManager::_WindowCreatedHandlers });
|
||||
_monarch.WindowClosed({ get_weak(), &WindowManager::_WindowClosedHandlers });
|
||||
_monarch.FindTargetWindowRequested({ this, &WindowManager::_raiseFindTargetWindowRequested });
|
||||
_monarch.ShowTrayIconRequested([this](auto&&, auto&&) { _ShowTrayIconRequestedHandlers(*this, nullptr); });
|
||||
_monarch.HideTrayIconRequested([this](auto&&, auto&&) { _HideTrayIconRequestedHandlers(*this, nullptr); });
|
||||
_monarch.ShowNotificationIconRequested([this](auto&&, auto&&) { _ShowNotificationIconRequestedHandlers(*this, nullptr); });
|
||||
_monarch.HideNotificationIconRequested([this](auto&&, auto&&) { _HideNotificationIconRequestedHandlers(*this, nullptr); });
|
||||
_monarch.QuitAllRequested([this](auto&&, auto&&) { _QuitAllRequestedHandlers(*this, nullptr); });
|
||||
|
||||
_BecameMonarchHandlers(*this, nullptr);
|
||||
|
@ -529,7 +529,7 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
|
|||
|
||||
void WindowManager::SummonAllWindows()
|
||||
{
|
||||
if constexpr (Feature_TrayIcon::IsEnabled())
|
||||
if constexpr (Feature_NotificationIcon::IsEnabled())
|
||||
{
|
||||
_monarch.SummonAllWindows();
|
||||
}
|
||||
|
@ -556,28 +556,28 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
|
|||
}
|
||||
|
||||
// Method Description:
|
||||
// - Ask the monarch to show a tray icon.
|
||||
// - Ask the monarch to show a notification icon.
|
||||
// Arguments:
|
||||
// - <none>
|
||||
// Return Value:
|
||||
// - <none>
|
||||
winrt::fire_and_forget WindowManager::RequestShowTrayIcon()
|
||||
winrt::fire_and_forget WindowManager::RequestShowNotificationIcon()
|
||||
{
|
||||
co_await winrt::resume_background();
|
||||
_peasant.RequestShowTrayIcon();
|
||||
_peasant.RequestShowNotificationIcon();
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Ask the monarch to hide its tray icon.
|
||||
// - Ask the monarch to hide its notification icon.
|
||||
// Arguments:
|
||||
// - <none>
|
||||
// Return Value:
|
||||
// - <none>
|
||||
winrt::fire_and_forget WindowManager::RequestHideTrayIcon()
|
||||
winrt::fire_and_forget WindowManager::RequestHideNotificationIcon()
|
||||
{
|
||||
auto strongThis{ get_strong() };
|
||||
co_await winrt::resume_background();
|
||||
_peasant.RequestHideTrayIcon();
|
||||
_peasant.RequestHideNotificationIcon();
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
|
|
|
@ -45,8 +45,8 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
|
|||
uint64_t GetNumberOfPeasants();
|
||||
Windows::Foundation::Collections::IVectorView<winrt::Microsoft::Terminal::Remoting::PeasantInfo> GetPeasantInfos();
|
||||
|
||||
winrt::fire_and_forget RequestShowTrayIcon();
|
||||
winrt::fire_and_forget RequestHideTrayIcon();
|
||||
winrt::fire_and_forget RequestShowNotificationIcon();
|
||||
winrt::fire_and_forget RequestHideNotificationIcon();
|
||||
winrt::fire_and_forget RequestQuitAll();
|
||||
bool DoesQuakeWindowExist();
|
||||
void UpdateActiveTabTitle(winrt::hstring title);
|
||||
|
@ -55,8 +55,8 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
|
|||
TYPED_EVENT(BecameMonarch, 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(ShowTrayIconRequested, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
|
||||
TYPED_EVENT(HideTrayIconRequested, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
|
||||
TYPED_EVENT(ShowNotificationIconRequested, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
|
||||
TYPED_EVENT(HideNotificationIconRequested, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
|
||||
TYPED_EVENT(QuitAllRequested, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
|
||||
|
||||
private:
|
||||
|
|
|
@ -14,8 +14,8 @@ namespace Microsoft.Terminal.Remoting
|
|||
Boolean IsMonarch { get; };
|
||||
void SummonWindow(SummonWindowSelectionArgs args);
|
||||
void SummonAllWindows();
|
||||
void RequestShowTrayIcon();
|
||||
void RequestHideTrayIcon();
|
||||
void RequestShowNotificationIcon();
|
||||
void RequestHideNotificationIcon();
|
||||
UInt64 GetNumberOfPeasants();
|
||||
void RequestQuitAll();
|
||||
void UpdateActiveTabTitle(String title);
|
||||
|
@ -25,8 +25,8 @@ namespace Microsoft.Terminal.Remoting
|
|||
event Windows.Foundation.TypedEventHandler<Object, Object> BecameMonarch;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> WindowCreated;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> WindowClosed;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> ShowTrayIconRequested;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> HideTrayIconRequested;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> ShowNotificationIconRequested;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> HideNotificationIconRequested;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> QuitAllRequested;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -173,7 +173,7 @@ namespace winrt::TerminalApp::implementation
|
|||
}
|
||||
else if (const auto& realArgs = args.ActionArgs().try_as<SplitPaneArgs>())
|
||||
{
|
||||
_SplitPane(realArgs.SplitStyle(),
|
||||
_SplitPane(realArgs.SplitDirection(),
|
||||
realArgs.SplitMode(),
|
||||
// This is safe, we're already filtering so the value is (0, 1)
|
||||
::base::saturated_cast<float>(realArgs.SplitSize()),
|
||||
|
|
|
@ -274,18 +274,18 @@ void AppCommandlineArgs::_buildSplitPaneParser()
|
|||
// _getNewTerminalArgs MUST be called before parsing any other options,
|
||||
// as it might clear those options while finding the commandline
|
||||
auto terminalArgs{ _getNewTerminalArgs(subcommand) };
|
||||
auto style{ SplitState::Automatic };
|
||||
auto style{ SplitDirection::Automatic };
|
||||
// Make sure to use the `Option`s here to check if they were set -
|
||||
// _getNewTerminalArgs might reset them while parsing a commandline
|
||||
if ((*subcommand._horizontalOption || *subcommand._verticalOption))
|
||||
{
|
||||
if (_splitHorizontal)
|
||||
{
|
||||
style = SplitState::Horizontal;
|
||||
style = SplitDirection::Down;
|
||||
}
|
||||
else if (_splitVertical)
|
||||
{
|
||||
style = SplitState::Vertical;
|
||||
style = SplitDirection::Right;
|
||||
}
|
||||
}
|
||||
const auto splitMode{ subcommand._duplicateOption && _splitDuplicate ? SplitType::Duplicate : SplitType::Manual };
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
|
||||
#include <LibraryResources.h>
|
||||
#include <WtExeUtils.h>
|
||||
#include <wil/token_helpers.h >
|
||||
|
||||
#include "../../types/inc/utils.hpp"
|
||||
|
||||
|
@ -133,6 +134,8 @@ static Documents::Run _BuildErrorRun(const winrt::hstring& text, const ResourceD
|
|||
// Method Description:
|
||||
// - Returns whether the user is either a member of the Administrators group or
|
||||
// is currently elevated.
|
||||
// - This will return **FALSE** if the user has UAC disabled entirely, because
|
||||
// there's no separation of power between the user and an admin in that case.
|
||||
// Return Value:
|
||||
// - true if the user is an administrator
|
||||
static bool _isUserAdmin() noexcept
|
||||
|
@ -1478,9 +1481,9 @@ namespace winrt::TerminalApp::implementation
|
|||
return _root->IsQuakeWindow();
|
||||
}
|
||||
|
||||
bool AppLogic::GetMinimizeToTray()
|
||||
bool AppLogic::GetMinimizeToNotificationArea()
|
||||
{
|
||||
if constexpr (Feature_TrayIcon::IsEnabled())
|
||||
if constexpr (Feature_NotificationIcon::IsEnabled())
|
||||
{
|
||||
if (!_loadedInitialSettings)
|
||||
{
|
||||
|
@ -1488,7 +1491,7 @@ namespace winrt::TerminalApp::implementation
|
|||
LoadSettings();
|
||||
}
|
||||
|
||||
return _settings.GlobalSettings().MinimizeToTray();
|
||||
return _settings.GlobalSettings().MinimizeToNotificationArea();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1496,9 +1499,9 @@ namespace winrt::TerminalApp::implementation
|
|||
}
|
||||
}
|
||||
|
||||
bool AppLogic::GetAlwaysShowTrayIcon()
|
||||
bool AppLogic::GetAlwaysShowNotificationIcon()
|
||||
{
|
||||
if constexpr (Feature_TrayIcon::IsEnabled())
|
||||
if constexpr (Feature_NotificationIcon::IsEnabled())
|
||||
{
|
||||
if (!_loadedInitialSettings)
|
||||
{
|
||||
|
@ -1506,7 +1509,7 @@ namespace winrt::TerminalApp::implementation
|
|||
LoadSettings();
|
||||
}
|
||||
|
||||
return _settings.GlobalSettings().AlwaysShowTrayIcon();
|
||||
return _settings.GlobalSettings().AlwaysShowNotificationIcon();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -95,8 +95,8 @@ namespace winrt::TerminalApp::implementation
|
|||
|
||||
winrt::TerminalApp::TaskbarState TaskbarState();
|
||||
|
||||
bool GetMinimizeToTray();
|
||||
bool GetAlwaysShowTrayIcon();
|
||||
bool GetMinimizeToNotificationArea();
|
||||
bool GetAlwaysShowNotificationIcon();
|
||||
bool GetShowTitleInTitlebar();
|
||||
|
||||
winrt::Windows::Foundation::IAsyncOperation<winrt::Windows::UI::Xaml::Controls::ContentDialogResult> ShowDialog(winrt::Windows::UI::Xaml::Controls::ContentDialog dialog);
|
||||
|
|
|
@ -73,8 +73,8 @@ namespace TerminalApp
|
|||
|
||||
TaskbarState TaskbarState{ get; };
|
||||
|
||||
Boolean GetMinimizeToTray();
|
||||
Boolean GetAlwaysShowTrayIcon();
|
||||
Boolean GetMinimizeToNotificationArea();
|
||||
Boolean GetAlwaysShowNotificationIcon();
|
||||
Boolean GetShowTitleInTitlebar();
|
||||
|
||||
FindTargetWindowResult FindTargetWindow(String[] args);
|
||||
|
|
|
@ -147,7 +147,8 @@ Pane::BuildStartupState Pane::BuildStartupActions(uint32_t currentId, uint32_t n
|
|||
const auto terminalArgs{ newPane->GetTerminalArgsForPane() };
|
||||
// When creating a pane the split size is the size of the new pane
|
||||
// and not position.
|
||||
SplitPaneArgs args{ SplitType::Manual, _splitState, 1. - _desiredSplitPosition, terminalArgs };
|
||||
const auto splitDirection = _splitState == SplitState::Horizontal ? SplitDirection::Down : SplitDirection::Right;
|
||||
SplitPaneArgs args{ SplitType::Manual, splitDirection, 1. - _desiredSplitPosition, terminalArgs };
|
||||
actionAndArgs.Args(args);
|
||||
|
||||
return actionAndArgs;
|
||||
|
@ -1291,7 +1292,7 @@ void Pane::UpdateSettings(const TerminalSettingsCreateResult& settings, const Pr
|
|||
// - splitType: How the pane should be attached
|
||||
// Return Value:
|
||||
// - the new reference to the child created from the current pane.
|
||||
std::shared_ptr<Pane> Pane::AttachPane(std::shared_ptr<Pane> pane, SplitState splitType)
|
||||
std::shared_ptr<Pane> Pane::AttachPane(std::shared_ptr<Pane> pane, SplitDirection splitType)
|
||||
{
|
||||
// Splice the new pane into the tree
|
||||
const auto [first, _] = _Split(splitType, .5, pane);
|
||||
|
@ -2002,7 +2003,7 @@ void Pane::_SetupEntranceAnimation()
|
|||
// Note:
|
||||
// - This method is highly similar to Pane::PreCalculateAutoSplit
|
||||
std::optional<bool> Pane::PreCalculateCanSplit(const std::shared_ptr<Pane> target,
|
||||
SplitState splitType,
|
||||
SplitDirection splitType,
|
||||
const float splitSize,
|
||||
const winrt::Windows::Foundation::Size availableSpace) const
|
||||
{
|
||||
|
@ -2016,12 +2017,7 @@ std::optional<bool> Pane::PreCalculateCanSplit(const std::shared_ptr<Pane> targe
|
|||
// the available space to calculate which direction to split in.
|
||||
const Size minSize = _GetMinSize();
|
||||
|
||||
if (splitType == SplitState::None)
|
||||
{
|
||||
return { false };
|
||||
}
|
||||
|
||||
else if (splitType == SplitState::Vertical)
|
||||
if (splitType == SplitDirection::Left || splitType == SplitDirection::Right)
|
||||
{
|
||||
const auto widthMinusSeparator = availableSpace.Width - CombinedPaneBorderSize;
|
||||
const auto newFirstWidth = widthMinusSeparator * firstPrecent;
|
||||
|
@ -2030,7 +2026,7 @@ std::optional<bool> Pane::PreCalculateCanSplit(const std::shared_ptr<Pane> targe
|
|||
return { newFirstWidth > minSize.Width && newSecondWidth > minSize.Width };
|
||||
}
|
||||
|
||||
else if (splitType == SplitState::Horizontal)
|
||||
else if (splitType == SplitDirection::Up || splitType == SplitDirection::Down)
|
||||
{
|
||||
const auto heightMinusSeparator = availableSpace.Height - CombinedPaneBorderSize;
|
||||
const auto newFirstHeight = heightMinusSeparator * firstPrecent;
|
||||
|
@ -2083,8 +2079,8 @@ std::optional<bool> Pane::PreCalculateCanSplit(const std::shared_ptr<Pane> targe
|
|||
// - profile: The profile to associate with the newly created pane.
|
||||
// - control: A TermControl to use in the new pane.
|
||||
// Return Value:
|
||||
// - The two newly created Panes
|
||||
std::pair<std::shared_ptr<Pane>, std::shared_ptr<Pane>> Pane::Split(SplitState splitType,
|
||||
// - The two newly created Panes, with the original pane first
|
||||
std::pair<std::shared_ptr<Pane>, std::shared_ptr<Pane>> Pane::Split(SplitDirection splitType,
|
||||
const float splitSize,
|
||||
const Profile& profile,
|
||||
const TermControl& control)
|
||||
|
@ -2147,18 +2143,18 @@ bool Pane::ToggleSplitOrientation()
|
|||
// Method Description:
|
||||
// - Converts an "automatic" split type into either Vertical or Horizontal,
|
||||
// based upon the current dimensions of the Pane.
|
||||
// - If any of the other SplitState values are passed in, they're returned
|
||||
// unmodified.
|
||||
// - Similarly, if Up/Down or Left/Right are provided a Horizontal or Vertical
|
||||
// split type will be returned.
|
||||
// Arguments:
|
||||
// - splitType: The SplitState to attempt to convert
|
||||
// - splitType: The SplitDirection to attempt to convert
|
||||
// Return Value:
|
||||
// - None if splitType was None, otherwise one of Horizontal or Vertical
|
||||
SplitState Pane::_convertAutomaticSplitState(const SplitState& splitType) const
|
||||
// - One of Horizontal or Vertical
|
||||
SplitState Pane::_convertAutomaticOrDirectionalSplitState(const SplitDirection& splitType) const
|
||||
{
|
||||
// Careful here! If the pane doesn't yet have a size, these dimensions will
|
||||
// be 0, and we'll always return Vertical.
|
||||
|
||||
if (splitType == SplitState::Automatic)
|
||||
if (splitType == SplitDirection::Automatic)
|
||||
{
|
||||
// If the requested split type was "auto", determine which direction to
|
||||
// split based on our current dimensions
|
||||
|
@ -2166,7 +2162,12 @@ SplitState Pane::_convertAutomaticSplitState(const SplitState& splitType) const
|
|||
gsl::narrow_cast<float>(_root.ActualHeight()) };
|
||||
return actualSize.Width >= actualSize.Height ? SplitState::Vertical : SplitState::Horizontal;
|
||||
}
|
||||
return splitType;
|
||||
if (splitType == SplitDirection::Up || splitType == SplitDirection::Down)
|
||||
{
|
||||
return SplitState::Horizontal;
|
||||
}
|
||||
// All that is left is Left / Right which are vertical splits
|
||||
return SplitState::Vertical;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
|
@ -2177,17 +2178,12 @@ SplitState Pane::_convertAutomaticSplitState(const SplitState& splitType) const
|
|||
// - splitSize: what fraction of the pane the new pane should get
|
||||
// - newPane: the pane to add as a child
|
||||
// Return Value:
|
||||
// - The two newly created Panes
|
||||
std::pair<std::shared_ptr<Pane>, std::shared_ptr<Pane>> Pane::_Split(SplitState splitType,
|
||||
// - The two newly created Panes, with the original pane as the first pane.
|
||||
std::pair<std::shared_ptr<Pane>, std::shared_ptr<Pane>> Pane::_Split(SplitDirection splitType,
|
||||
const float splitSize,
|
||||
std::shared_ptr<Pane> newPane)
|
||||
{
|
||||
if (splitType == SplitState::None)
|
||||
{
|
||||
return { nullptr, nullptr };
|
||||
}
|
||||
|
||||
auto actualSplitType = _convertAutomaticSplitState(splitType);
|
||||
auto actualSplitType = _convertAutomaticOrDirectionalSplitState(splitType);
|
||||
|
||||
// Lock the create/close lock so that another operation won't concurrently
|
||||
// modify our tree
|
||||
|
@ -2218,9 +2214,16 @@ std::pair<std::shared_ptr<Pane>, std::shared_ptr<Pane>> Pane::_Split(SplitState
|
|||
// Move the new guid, control into the second.
|
||||
_firstChild = std::make_shared<Pane>(_profile, _control);
|
||||
_firstChild->_connectionState = std::exchange(_connectionState, ConnectionState::NotConnected);
|
||||
_secondChild = newPane;
|
||||
|
||||
// If we want the new pane to be the first child, swap the children
|
||||
if (splitType == SplitDirection::Up || splitType == SplitDirection::Left)
|
||||
{
|
||||
std::swap(_firstChild, _secondChild);
|
||||
}
|
||||
|
||||
_profile = nullptr;
|
||||
_control = { nullptr };
|
||||
_secondChild = newPane;
|
||||
|
||||
_CreateRowColDefinitions();
|
||||
|
||||
|
@ -2239,6 +2242,12 @@ std::pair<std::shared_ptr<Pane>, std::shared_ptr<Pane>> Pane::_Split(SplitState
|
|||
// Clear out our ID, only leaves should have IDs
|
||||
_id = {};
|
||||
|
||||
// Regardless of which child the new child is, we want to return the
|
||||
// original one first.
|
||||
if (splitType == SplitDirection::Up || splitType == SplitDirection::Left)
|
||||
{
|
||||
return { _secondChild, _firstChild };
|
||||
}
|
||||
return { _firstChild, _secondChild };
|
||||
}
|
||||
|
||||
|
@ -2874,10 +2883,10 @@ int Pane::GetLeafPaneCount() const noexcept
|
|||
// - availableSpace: The theoretical space that's available for this pane to be able to split.
|
||||
// Return Value:
|
||||
// - 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
|
||||
// SplitDirection that `target` would use for an `Automatic` split given
|
||||
// `availableSpace`
|
||||
std::optional<SplitState> Pane::PreCalculateAutoSplit(const std::shared_ptr<Pane> target,
|
||||
const winrt::Windows::Foundation::Size availableSpace) const
|
||||
std::optional<SplitDirection> Pane::PreCalculateAutoSplit(const std::shared_ptr<Pane> target,
|
||||
const winrt::Windows::Foundation::Size availableSpace) const
|
||||
{
|
||||
if (_IsLeaf())
|
||||
{
|
||||
|
@ -2885,7 +2894,7 @@ std::optional<SplitState> Pane::PreCalculateAutoSplit(const std::shared_ptr<Pane
|
|||
{
|
||||
//If this pane is a leaf, and it's the pane we're looking for, use
|
||||
//the available space to calculate which direction to split in.
|
||||
return availableSpace.Width > availableSpace.Height ? SplitState::Vertical : SplitState::Horizontal;
|
||||
return availableSpace.Width > availableSpace.Height ? SplitDirection::Right : SplitDirection::Down;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -44,6 +44,13 @@ enum class Borders : int
|
|||
};
|
||||
DEFINE_ENUM_FLAG_OPERATORS(Borders);
|
||||
|
||||
enum class SplitState : int
|
||||
{
|
||||
None = 0,
|
||||
Horizontal = 1,
|
||||
Vertical = 2
|
||||
};
|
||||
|
||||
class Pane : public std::enable_shared_from_this<Pane>
|
||||
{
|
||||
public:
|
||||
|
@ -93,23 +100,23 @@ public:
|
|||
std::shared_ptr<Pane> NextPane(const std::shared_ptr<Pane> pane);
|
||||
std::shared_ptr<Pane> PreviousPane(const std::shared_ptr<Pane> pane);
|
||||
|
||||
std::pair<std::shared_ptr<Pane>, std::shared_ptr<Pane>> Split(winrt::Microsoft::Terminal::Settings::Model::SplitState splitType,
|
||||
std::pair<std::shared_ptr<Pane>, std::shared_ptr<Pane>> Split(winrt::Microsoft::Terminal::Settings::Model::SplitDirection splitType,
|
||||
const float splitSize,
|
||||
const winrt::Microsoft::Terminal::Settings::Model::Profile& profile,
|
||||
const winrt::Microsoft::Terminal::Control::TermControl& control);
|
||||
bool ToggleSplitOrientation();
|
||||
float CalcSnappedDimension(const bool widthOrHeight, const float dimension) const;
|
||||
std::optional<winrt::Microsoft::Terminal::Settings::Model::SplitState> PreCalculateAutoSplit(const std::shared_ptr<Pane> target,
|
||||
const winrt::Windows::Foundation::Size parentSize) const;
|
||||
std::optional<winrt::Microsoft::Terminal::Settings::Model::SplitDirection> PreCalculateAutoSplit(const std::shared_ptr<Pane> target,
|
||||
const winrt::Windows::Foundation::Size parentSize) const;
|
||||
std::optional<bool> PreCalculateCanSplit(const std::shared_ptr<Pane> target,
|
||||
winrt::Microsoft::Terminal::Settings::Model::SplitState splitType,
|
||||
winrt::Microsoft::Terminal::Settings::Model::SplitDirection splitType,
|
||||
const float splitSize,
|
||||
const winrt::Windows::Foundation::Size availableSpace) const;
|
||||
void Shutdown();
|
||||
void Close();
|
||||
|
||||
std::shared_ptr<Pane> AttachPane(std::shared_ptr<Pane> pane,
|
||||
winrt::Microsoft::Terminal::Settings::Model::SplitState splitType);
|
||||
winrt::Microsoft::Terminal::Settings::Model::SplitDirection splitType);
|
||||
std::shared_ptr<Pane> DetachPane(std::shared_ptr<Pane> pane);
|
||||
|
||||
int GetLeafPaneCount() const noexcept;
|
||||
|
@ -174,7 +181,7 @@ private:
|
|||
|
||||
std::shared_ptr<Pane> _firstChild{ nullptr };
|
||||
std::shared_ptr<Pane> _secondChild{ nullptr };
|
||||
winrt::Microsoft::Terminal::Settings::Model::SplitState _splitState{ winrt::Microsoft::Terminal::Settings::Model::SplitState::None };
|
||||
SplitState _splitState{ SplitState::None };
|
||||
float _desiredSplitPosition;
|
||||
|
||||
std::optional<uint32_t> _id;
|
||||
|
@ -199,7 +206,7 @@ private:
|
|||
bool _HasFocusedChild() const noexcept;
|
||||
void _SetupChildCloseHandlers();
|
||||
|
||||
std::pair<std::shared_ptr<Pane>, std::shared_ptr<Pane>> _Split(winrt::Microsoft::Terminal::Settings::Model::SplitState splitType,
|
||||
std::pair<std::shared_ptr<Pane>, std::shared_ptr<Pane>> _Split(winrt::Microsoft::Terminal::Settings::Model::SplitDirection splitType,
|
||||
const float splitSize,
|
||||
std::shared_ptr<Pane> newPane);
|
||||
|
||||
|
@ -242,9 +249,9 @@ private:
|
|||
LayoutSizeNode _CreateMinSizeTree(const bool widthOrHeight) const;
|
||||
float _ClampSplitPosition(const bool widthOrHeight, const float requestedValue, const float totalSize) const;
|
||||
|
||||
winrt::Microsoft::Terminal::Settings::Model::SplitState _convertAutomaticSplitState(const winrt::Microsoft::Terminal::Settings::Model::SplitState& splitType) const;
|
||||
SplitState _convertAutomaticOrDirectionalSplitState(const winrt::Microsoft::Terminal::Settings::Model::SplitDirection& splitType) const;
|
||||
|
||||
std::optional<winrt::Microsoft::Terminal::Settings::Model::SplitState> _preCalculateAutoSplit(const std::shared_ptr<Pane> target, const winrt::Windows::Foundation::Size parentSize) const;
|
||||
std::optional<winrt::Microsoft::Terminal::Settings::Model::SplitDirection> _preCalculateAutoSplit(const std::shared_ptr<Pane> target, const winrt::Windows::Foundation::Size parentSize) const;
|
||||
|
||||
// Function Description:
|
||||
// - Returns true if the given direction can be used with the given split
|
||||
|
@ -255,24 +262,24 @@ private:
|
|||
// - Also used for moving focus between panes, which again happens _across_ a separator.
|
||||
// Arguments:
|
||||
// - direction: The Direction to compare
|
||||
// - splitType: The winrt::TerminalApp::SplitState to compare
|
||||
// - splitType: The SplitState to compare
|
||||
// Return Value:
|
||||
// - true iff the direction is perpendicular to the splitType. False for
|
||||
// winrt::TerminalApp::SplitState::None.
|
||||
// SplitState::None.
|
||||
template<typename T>
|
||||
static constexpr bool DirectionMatchesSplit(const T& direction,
|
||||
const winrt::Microsoft::Terminal::Settings::Model::SplitState& splitType)
|
||||
const SplitState& splitType)
|
||||
{
|
||||
if (splitType == winrt::Microsoft::Terminal::Settings::Model::SplitState::None)
|
||||
if (splitType == SplitState::None)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (splitType == winrt::Microsoft::Terminal::Settings::Model::SplitState::Horizontal)
|
||||
else if (splitType == SplitState::Horizontal)
|
||||
{
|
||||
return direction == T::Up ||
|
||||
direction == T::Down;
|
||||
}
|
||||
else if (splitType == winrt::Microsoft::Terminal::Settings::Model::SplitState::Vertical)
|
||||
else if (splitType == SplitState::Vertical)
|
||||
{
|
||||
return direction == T::Left ||
|
||||
direction == T::Right;
|
||||
|
|
|
@ -665,11 +665,11 @@
|
|||
<data name="CommandPaletteMenuItem" xml:space="preserve">
|
||||
<value>Command Palette</value>
|
||||
</data>
|
||||
<data name="TrayIconFocusTerminal" xml:space="preserve">
|
||||
<data name="NotificationIconFocusTerminal" xml:space="preserve">
|
||||
<value>Focus Terminal</value>
|
||||
<comment>This is displayed as a label for the context menu item that focuses the terminal.</comment>
|
||||
</data>
|
||||
<data name="TrayIconWindowSubmenu" xml:space="preserve">
|
||||
<data name="NotificationIconWindowSubmenu" xml:space="preserve">
|
||||
<value>Windows</value>
|
||||
<comment>This is displayed as a label for the context menu item that holds the submenu of available windows.</comment>
|
||||
</data>
|
||||
|
|
|
@ -289,7 +289,7 @@ namespace winrt::TerminalApp::implementation
|
|||
auto newControl = _InitControl(settings, debugConnection);
|
||||
_RegisterTerminalEvents(newControl);
|
||||
// Split (auto) with the debug tap.
|
||||
newTabImpl->SplitPane(SplitState::Automatic, 0.5f, profile, newControl);
|
||||
newTabImpl->SplitPane(SplitDirection::Automatic, 0.5f, profile, newControl);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -399,7 +399,7 @@ namespace winrt::TerminalApp::implementation
|
|||
try
|
||||
{
|
||||
_SetFocusedTab(tab);
|
||||
_SplitPane(tab, SplitState::Automatic, SplitType::Duplicate);
|
||||
_SplitPane(tab, SplitDirection::Automatic, SplitType::Duplicate);
|
||||
}
|
||||
CATCH_LOG();
|
||||
}
|
||||
|
|
|
@ -21,14 +21,12 @@
|
|||
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.pre.props" />
|
||||
<Import Project="..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props" Condition="Exists('..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props')" />
|
||||
<ItemDefinitionGroup>
|
||||
|
||||
<ClCompile>
|
||||
<!-- For CLI11: It uses dynamic_cast to cast types around, which depends
|
||||
on being compiled with RTTI (/GR). -->
|
||||
<RuntimeTypeInfo>true</RuntimeTypeInfo>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
|
||||
<!-- ========================= XAML files ======================== -->
|
||||
<ItemGroup>
|
||||
<!-- HERE BE DRAGONS:
|
||||
|
@ -238,7 +236,6 @@
|
|||
</ClCompile>
|
||||
<ClCompile Include="$(GeneratedFilesDir)module.g.cpp" />
|
||||
<ClCompile Include="Toast.cpp" />
|
||||
|
||||
</ItemGroup>
|
||||
<!-- ========================= idl Files ======================== -->
|
||||
<ItemGroup>
|
||||
|
@ -379,7 +376,6 @@
|
|||
</ItemDefinitionGroup>
|
||||
<!-- ========================= Globals ======================== -->
|
||||
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.post.props" />
|
||||
|
||||
<Import Project="..\..\..\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets" Condition="Exists('..\..\..\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets')" />
|
||||
<Import Project="..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets" Condition="Exists('..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets')" />
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
|
@ -388,8 +384,8 @@
|
|||
</PropertyGroup>
|
||||
<Error Condition="!Exists('$(OpenConsoleDir)\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(OpenConsoleDir)\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets'))" />
|
||||
<Error Condition="!Exists('$(OpenConsoleDir)\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(OpenConsoleDir)\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets'))" />
|
||||
<Error Condition="!Exists('$(OpenConsoleDir)\packages\Microsoft.VisualStudio.Setup.Configuration.Native.2.3.2262\build\native\Microsoft.VisualStudio.Setup.Configuration.Native.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.VisualStudio.Setup.Configuration.Native.2.3.2262\build\native\Microsoft.VisualStudio.Setup.Configuration.Native.targets'))" />
|
||||
</Target>
|
||||
|
||||
<!--
|
||||
By default, the PRI file will contain resource paths beginning with the
|
||||
project name. Since we enabled XBF embedding, this *also* includes App.xbf.
|
||||
|
@ -409,6 +405,5 @@
|
|||
</PackagingOutputs>
|
||||
</ItemGroup>
|
||||
</Target>
|
||||
|
||||
<Import Project="$(SolutionDir)build\rules\CollectWildcardResources.targets" />
|
||||
</Project>
|
||||
|
|
|
@ -827,7 +827,7 @@ namespace winrt::TerminalApp::implementation
|
|||
|
||||
if (altPressed && !debugTap)
|
||||
{
|
||||
this->_SplitPane(SplitState::Automatic,
|
||||
this->_SplitPane(SplitDirection::Automatic,
|
||||
SplitType::Manual,
|
||||
0.5f,
|
||||
newTerminalArgs);
|
||||
|
@ -1468,25 +1468,18 @@ namespace winrt::TerminalApp::implementation
|
|||
// Method Description:
|
||||
// - Split the focused pane either horizontally or vertically, and place the
|
||||
// given TermControl into the newly created pane.
|
||||
// - If splitType == SplitState::None, this method does nothing.
|
||||
// Arguments:
|
||||
// - splitType: one value from the TerminalApp::SplitState enum, indicating how the
|
||||
// - splitDirection: one value from the TerminalApp::SplitDirection enum, indicating how the
|
||||
// new pane should be split from its parent.
|
||||
// - splitMode: value from TerminalApp::SplitType enum, indicating the profile to be used in the newly split pane.
|
||||
// - 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 SplitState splitType,
|
||||
void TerminalPage::_SplitPane(const SplitDirection splitDirection,
|
||||
const SplitType splitMode,
|
||||
const float splitSize,
|
||||
const NewTerminalArgs& newTerminalArgs)
|
||||
{
|
||||
// Do nothing if we're requesting no split.
|
||||
if (splitType == SplitState::None)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const auto focusedTab{ _GetFocusedTabImpl() };
|
||||
|
||||
// Do nothing if no TerminalTab is focused
|
||||
|
@ -1495,33 +1488,26 @@ namespace winrt::TerminalApp::implementation
|
|||
return;
|
||||
}
|
||||
|
||||
_SplitPane(*focusedTab, splitType, splitMode, splitSize, newTerminalArgs);
|
||||
_SplitPane(*focusedTab, splitDirection, splitMode, splitSize, newTerminalArgs);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Split the focused pane of the given tab, either horizontally or vertically, and place the
|
||||
// given TermControl into the newly created pane.
|
||||
// - If splitType == SplitState::None, this method does nothing.
|
||||
// Arguments:
|
||||
// - tab: The tab that is going to be split.
|
||||
// - splitType: one value from the TerminalApp::SplitState enum, indicating how the
|
||||
// - splitDirection: one value from the TerminalApp::SplitDirection enum, indicating how the
|
||||
// new pane should be split from its parent.
|
||||
// - splitMode: value from TerminalApp::SplitType enum, indicating the profile to be used in the newly split pane.
|
||||
// - 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(TerminalTab& tab,
|
||||
const SplitState splitType,
|
||||
const SplitDirection splitDirection,
|
||||
const SplitType splitMode,
|
||||
const float splitSize,
|
||||
const NewTerminalArgs& newTerminalArgs)
|
||||
{
|
||||
// Do nothing if we're requesting no split.
|
||||
if (splitType == SplitState::None)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
TerminalSettingsCreateResult controlSettings{ nullptr };
|
||||
|
@ -1567,8 +1553,8 @@ namespace winrt::TerminalApp::implementation
|
|||
const float contentHeight = ::base::saturated_cast<float>(_tabContent.ActualHeight());
|
||||
const winrt::Windows::Foundation::Size availableSpace{ contentWidth, contentHeight };
|
||||
|
||||
auto realSplitType = splitType;
|
||||
if (realSplitType == SplitState::Automatic)
|
||||
auto realSplitType = splitDirection;
|
||||
if (realSplitType == SplitDirection::Automatic)
|
||||
{
|
||||
realSplitType = tab.PreCalculateAutoSplit(availableSpace);
|
||||
}
|
||||
|
|
|
@ -269,12 +269,12 @@ namespace winrt::TerminalApp::implementation
|
|||
|
||||
void _Scroll(ScrollDirection scrollDirection, const Windows::Foundation::IReference<uint32_t>& rowsToScroll);
|
||||
|
||||
void _SplitPane(const Microsoft::Terminal::Settings::Model::SplitState splitType,
|
||||
void _SplitPane(const Microsoft::Terminal::Settings::Model::SplitDirection splitType,
|
||||
const Microsoft::Terminal::Settings::Model::SplitType splitMode = Microsoft::Terminal::Settings::Model::SplitType::Manual,
|
||||
const float splitSize = 0.5f,
|
||||
const Microsoft::Terminal::Settings::Model::NewTerminalArgs& newTerminalArgs = nullptr);
|
||||
void _SplitPane(TerminalTab& tab,
|
||||
const Microsoft::Terminal::Settings::Model::SplitState splitType,
|
||||
const Microsoft::Terminal::Settings::Model::SplitDirection splitType,
|
||||
const Microsoft::Terminal::Settings::Model::SplitType splitMode = Microsoft::Terminal::Settings::Model::SplitType::Manual,
|
||||
const float splitSize = 0.5f,
|
||||
const Microsoft::Terminal::Settings::Model::NewTerminalArgs& newTerminalArgs = nullptr);
|
||||
|
|
|
@ -490,40 +490,43 @@ namespace winrt::TerminalApp::implementation
|
|||
// - control: A TermControl to use in the new pane.
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void TerminalTab::SplitPane(SplitState splitType,
|
||||
void TerminalTab::SplitPane(SplitDirection splitType,
|
||||
const float splitSize,
|
||||
const Profile& profile,
|
||||
TermControl& control)
|
||||
{
|
||||
// Make sure to take the ID before calling Split() - Split() will clear out the active pane's ID
|
||||
const auto activePaneId = _activePane->Id();
|
||||
auto [first, second] = _activePane->Split(splitType, splitSize, profile, control);
|
||||
// Depending on which direction will be split, the new pane can be
|
||||
// either the first or second child, but this will always return the
|
||||
// original pane first.
|
||||
auto [original, newPane] = _activePane->Split(splitType, splitSize, profile, control);
|
||||
if (activePaneId)
|
||||
{
|
||||
first->Id(activePaneId.value());
|
||||
second->Id(_nextPaneId);
|
||||
original->Id(activePaneId.value());
|
||||
newPane->Id(_nextPaneId);
|
||||
++_nextPaneId;
|
||||
}
|
||||
else
|
||||
{
|
||||
first->Id(_nextPaneId);
|
||||
original->Id(_nextPaneId);
|
||||
++_nextPaneId;
|
||||
second->Id(_nextPaneId);
|
||||
newPane->Id(_nextPaneId);
|
||||
++_nextPaneId;
|
||||
}
|
||||
_activePane = first;
|
||||
_activePane = original;
|
||||
|
||||
// Add a event handlers to the new panes' GotFocus event. When the pane
|
||||
// gains focus, we'll mark it as the new active pane.
|
||||
_AttachEventHandlersToControl(second->Id().value(), control);
|
||||
_AttachEventHandlersToPane(first);
|
||||
_AttachEventHandlersToPane(second);
|
||||
_AttachEventHandlersToControl(newPane->Id().value(), control);
|
||||
_AttachEventHandlersToPane(original);
|
||||
_AttachEventHandlersToPane(newPane);
|
||||
|
||||
// Immediately update our tracker of the focused pane now. If we're
|
||||
// splitting panes during startup (from a commandline), then it's
|
||||
// possible that the focus events won't propagate immediately. Updating
|
||||
// the focus here will give the same effect though.
|
||||
_UpdateActivePane(second);
|
||||
_UpdateActivePane(newPane);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
|
@ -609,7 +612,7 @@ namespace winrt::TerminalApp::implementation
|
|||
const auto previousId = _activePane->Id();
|
||||
|
||||
// Add the new pane as an automatic split on the active pane.
|
||||
auto first = _activePane->AttachPane(pane, SplitState::Automatic);
|
||||
auto first = _activePane->AttachPane(pane, SplitDirection::Automatic);
|
||||
|
||||
// under current assumptions this condition should always be true.
|
||||
if (previousId)
|
||||
|
@ -1515,14 +1518,14 @@ namespace winrt::TerminalApp::implementation
|
|||
// Arguments:
|
||||
// - availableSpace: The theoretical space that's available for this Tab's content
|
||||
// Return Value:
|
||||
// - The SplitState that we should use for an `Automatic` split given
|
||||
// - The SplitDirection that we should use for an `Automatic` split given
|
||||
// `availableSpace`
|
||||
SplitState TerminalTab::PreCalculateAutoSplit(winrt::Windows::Foundation::Size availableSpace) const
|
||||
SplitDirection TerminalTab::PreCalculateAutoSplit(winrt::Windows::Foundation::Size availableSpace) const
|
||||
{
|
||||
return _rootPane->PreCalculateAutoSplit(_activePane, availableSpace).value_or(SplitState::Vertical);
|
||||
return _rootPane->PreCalculateAutoSplit(_activePane, availableSpace).value_or(SplitDirection::Right);
|
||||
}
|
||||
|
||||
bool TerminalTab::PreCalculateCanSplit(SplitState splitType,
|
||||
bool TerminalTab::PreCalculateCanSplit(SplitDirection splitType,
|
||||
const float splitSize,
|
||||
winrt::Windows::Foundation::Size availableSpace) const
|
||||
{
|
||||
|
|
|
@ -38,7 +38,7 @@ namespace winrt::TerminalApp::implementation
|
|||
std::shared_ptr<Pane> DetachPane();
|
||||
void AttachPane(std::shared_ptr<Pane> pane);
|
||||
|
||||
void SplitPane(winrt::Microsoft::Terminal::Settings::Model::SplitState splitType,
|
||||
void SplitPane(winrt::Microsoft::Terminal::Settings::Model::SplitDirection splitType,
|
||||
const float splitSize,
|
||||
const winrt::Microsoft::Terminal::Settings::Model::Profile& profile,
|
||||
winrt::Microsoft::Terminal::Control::TermControl& control);
|
||||
|
@ -51,8 +51,8 @@ namespace winrt::TerminalApp::implementation
|
|||
winrt::fire_and_forget ActivateBellIndicatorTimer();
|
||||
|
||||
float CalcSnappedDimension(const bool widthOrHeight, const float dimension) const;
|
||||
winrt::Microsoft::Terminal::Settings::Model::SplitState PreCalculateAutoSplit(winrt::Windows::Foundation::Size rootSize) const;
|
||||
bool PreCalculateCanSplit(winrt::Microsoft::Terminal::Settings::Model::SplitState splitType,
|
||||
winrt::Microsoft::Terminal::Settings::Model::SplitDirection PreCalculateAutoSplit(winrt::Windows::Foundation::Size rootSize) const;
|
||||
bool PreCalculateCanSplit(winrt::Microsoft::Terminal::Settings::Model::SplitDirection splitType,
|
||||
const float splitSize,
|
||||
winrt::Windows::Foundation::Size availableSpace) const;
|
||||
|
||||
|
|
|
@ -199,8 +199,8 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
|||
}
|
||||
}
|
||||
|
||||
bool GlobalAppearance::FeatureTrayIconEnabled() const noexcept
|
||||
bool GlobalAppearance::FeatureNotificationIconEnabled() const noexcept
|
||||
{
|
||||
return Feature_TrayIcon::IsEnabled();
|
||||
return Feature_NotificationIcon::IsEnabled();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
|||
|
||||
void OnNavigatedTo(const winrt::Windows::UI::Xaml::Navigation::NavigationEventArgs& e);
|
||||
|
||||
bool FeatureTrayIconEnabled() const noexcept;
|
||||
bool FeatureNotificationIconEnabled() const noexcept;
|
||||
|
||||
WINRT_PROPERTY(Editor::GlobalAppearancePageNavigationState, State, nullptr);
|
||||
GETSET_BINDABLE_ENUM_SETTING(Theme, winrt::Windows::UI::Xaml::ElementTheme, State().Globals, Theme);
|
||||
|
|
|
@ -26,6 +26,6 @@ namespace Microsoft.Terminal.Settings.Editor
|
|||
IInspectable CurrentTabWidthMode;
|
||||
Windows.Foundation.Collections.IObservableVector<Microsoft.Terminal.Settings.Editor.EnumEntry> TabWidthModeList { get; };
|
||||
|
||||
Boolean FeatureTrayIconEnabled { get; };
|
||||
Boolean FeatureNotificationIconEnabled { get; };
|
||||
}
|
||||
}
|
||||
|
|
|
@ -85,16 +85,16 @@
|
|||
<ToggleSwitch IsOn="{x:Bind local:Converters.InvertBoolean(State.Globals.DisableAnimations), BindBack=State.Globals.SetInvertedDisableAnimationsValue, Mode=TwoWay}" />
|
||||
</local:SettingContainer>
|
||||
|
||||
<!-- Always Show Tray Icon -->
|
||||
<local:SettingContainer x:Uid="Globals_AlwaysShowTrayIcon"
|
||||
Visibility="{x:Bind FeatureTrayIconEnabled}">
|
||||
<ToggleSwitch IsOn="{x:Bind State.Globals.AlwaysShowTrayIcon, Mode=TwoWay}" />
|
||||
<!-- Always Show Notification Icon -->
|
||||
<local:SettingContainer x:Uid="Globals_AlwaysShowNotificationIcon"
|
||||
Visibility="{x:Bind FeatureNotificationIconEnabled}">
|
||||
<ToggleSwitch IsOn="{x:Bind State.Globals.AlwaysShowNotificationIcon, Mode=TwoWay}" />
|
||||
</local:SettingContainer>
|
||||
|
||||
<!-- Minimize To Tray -->
|
||||
<local:SettingContainer x:Uid="Globals_MinimizeToTray"
|
||||
Visibility="{x:Bind FeatureTrayIconEnabled}">
|
||||
<ToggleSwitch IsOn="{x:Bind State.Globals.MinimizeToTray, Mode=TwoWay}" />
|
||||
<!-- Minimize To Notification Area -->
|
||||
<local:SettingContainer x:Uid="Globals_MinimizeToNotificationArea"
|
||||
Visibility="{x:Bind FeatureNotificationIconEnabled}">
|
||||
<ToggleSwitch IsOn="{x:Bind State.Globals.MinimizeToNotificationArea, Mode=TwoWay}" />
|
||||
</local:SettingContainer>
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
|
|
|
@ -1106,13 +1106,13 @@
|
|||
<value>Pane animations</value>
|
||||
<comment>Header for a control to toggle animations on panes. "Enabled" value enables the animations.</comment>
|
||||
</data>
|
||||
<data name="Globals_AlwaysShowTrayIcon.Header" xml:space="preserve">
|
||||
<data name="Globals_AlwaysShowNotificationIcon.Header" xml:space="preserve">
|
||||
<value>Always display an icon in the notification area</value>
|
||||
<comment>Header for a control to toggle whether the tray icon should always be shown.</comment>
|
||||
<comment>Header for a control to toggle whether the notification icon should always be shown.</comment>
|
||||
</data>
|
||||
<data name="Globals_MinimizeToTray.Header" xml:space="preserve">
|
||||
<data name="Globals_MinimizeToNotificationArea.Header" xml:space="preserve">
|
||||
<value>Hide Terminal in the notification area when it is minimized</value>
|
||||
<comment>Header for a control to toggle whether the terminal should hide itself in the tray instead of the taskbar when minimized.</comment>
|
||||
<comment>Header for a control to toggle whether the terminal should hide itself in the notification area instead of the taskbar when minimized.</comment>
|
||||
</data>
|
||||
<data name="SettingContainer_OverrideMessageBaseLayer" xml:space="preserve">
|
||||
<value>Reset to inherited value.</value>
|
||||
|
@ -1234,4 +1234,4 @@
|
|||
<value>Bold font with bright colors</value>
|
||||
<comment>An option to choose from for the "intense text format" setting. When selected, "intense" text will be rendered as both bold text and in a brighter color</comment>
|
||||
</data>
|
||||
</root>
|
||||
</root>
|
||||
|
|
|
@ -399,13 +399,19 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
|||
|
||||
// This text is intentionally _not_ localized, to attempt to mirror the
|
||||
// exact syntax that the property would have in JSON.
|
||||
switch (SplitStyle())
|
||||
switch (SplitDirection())
|
||||
{
|
||||
case SplitState::Vertical:
|
||||
ss << L"split: vertical, ";
|
||||
case SplitDirection::Up:
|
||||
ss << L"split: up, ";
|
||||
break;
|
||||
case SplitState::Horizontal:
|
||||
ss << L"split: horizontal, ";
|
||||
case SplitDirection::Right:
|
||||
ss << L"split: right, ";
|
||||
break;
|
||||
case SplitDirection::Down:
|
||||
ss << L"split: down, ";
|
||||
break;
|
||||
case SplitDirection::Left:
|
||||
ss << L"split: left, ";
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -674,21 +674,21 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
|||
struct SplitPaneArgs : public SplitPaneArgsT<SplitPaneArgs>
|
||||
{
|
||||
SplitPaneArgs() = default;
|
||||
SplitPaneArgs(SplitType splitMode, SplitState style, double size, const Model::NewTerminalArgs& terminalArgs) :
|
||||
SplitPaneArgs(SplitType splitMode, SplitDirection direction, double size, const Model::NewTerminalArgs& terminalArgs) :
|
||||
_SplitMode{ splitMode },
|
||||
_SplitStyle{ style },
|
||||
_SplitDirection{ direction },
|
||||
_SplitSize{ size },
|
||||
_TerminalArgs{ terminalArgs } {};
|
||||
SplitPaneArgs(SplitState style, double size, const Model::NewTerminalArgs& terminalArgs) :
|
||||
_SplitStyle{ style },
|
||||
SplitPaneArgs(SplitDirection direction, double size, const Model::NewTerminalArgs& terminalArgs) :
|
||||
_SplitDirection{ direction },
|
||||
_SplitSize{ size },
|
||||
_TerminalArgs{ terminalArgs } {};
|
||||
SplitPaneArgs(SplitState style, const Model::NewTerminalArgs& terminalArgs) :
|
||||
_SplitStyle{ style },
|
||||
SplitPaneArgs(SplitDirection direction, const Model::NewTerminalArgs& terminalArgs) :
|
||||
_SplitDirection{ direction },
|
||||
_TerminalArgs{ terminalArgs } {};
|
||||
SplitPaneArgs(SplitType splitMode) :
|
||||
_SplitMode{ splitMode } {};
|
||||
ACTION_ARG(SplitState, SplitStyle, SplitState::Automatic);
|
||||
ACTION_ARG(Model::SplitDirection, SplitDirection, SplitDirection::Automatic);
|
||||
WINRT_PROPERTY(Model::NewTerminalArgs, TerminalArgs, nullptr);
|
||||
ACTION_ARG(SplitType, SplitMode, SplitType::Manual);
|
||||
ACTION_ARG(double, SplitSize, .5);
|
||||
|
@ -705,7 +705,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
|||
auto otherAsUs = other.try_as<SplitPaneArgs>();
|
||||
if (otherAsUs)
|
||||
{
|
||||
return otherAsUs->_SplitStyle == _SplitStyle &&
|
||||
return otherAsUs->_SplitDirection == _SplitDirection &&
|
||||
(otherAsUs->_TerminalArgs ? otherAsUs->_TerminalArgs.Equals(_TerminalArgs) :
|
||||
otherAsUs->_TerminalArgs == _TerminalArgs) &&
|
||||
otherAsUs->_SplitSize == _SplitSize &&
|
||||
|
@ -718,7 +718,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
|||
// LOAD BEARING: Not using make_self here _will_ break you in the future!
|
||||
auto args = winrt::make_self<SplitPaneArgs>();
|
||||
args->_TerminalArgs = NewTerminalArgs::FromJson(json);
|
||||
JsonUtils::GetValueForKey(json, SplitKey, args->_SplitStyle);
|
||||
JsonUtils::GetValueForKey(json, SplitKey, args->_SplitDirection);
|
||||
JsonUtils::GetValueForKey(json, SplitModeKey, args->_SplitMode);
|
||||
JsonUtils::GetValueForKey(json, SplitSizeKey, args->_SplitSize);
|
||||
if (args->SplitSize() >= 1 || args->SplitSize() <= 0)
|
||||
|
@ -735,7 +735,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
|||
}
|
||||
const auto args{ get_self<SplitPaneArgs>(val) };
|
||||
auto json{ NewTerminalArgs::ToJson(args->_TerminalArgs) };
|
||||
JsonUtils::SetValueForKey(json, SplitKey, args->_SplitStyle);
|
||||
JsonUtils::SetValueForKey(json, SplitKey, args->_SplitDirection);
|
||||
JsonUtils::SetValueForKey(json, SplitModeKey, args->_SplitMode);
|
||||
JsonUtils::SetValueForKey(json, SplitSizeKey, args->_SplitSize);
|
||||
return json;
|
||||
|
@ -743,7 +743,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
|||
IActionArgs Copy() const
|
||||
{
|
||||
auto copy{ winrt::make_self<SplitPaneArgs>() };
|
||||
copy->_SplitStyle = _SplitStyle;
|
||||
copy->_SplitDirection = _SplitDirection;
|
||||
copy->_TerminalArgs = _TerminalArgs.Copy();
|
||||
copy->_SplitMode = _SplitMode;
|
||||
copy->_SplitSize = _SplitSize;
|
||||
|
@ -751,7 +751,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
|||
}
|
||||
size_t Hash() const
|
||||
{
|
||||
return ::Microsoft::Terminal::Settings::Model::HashUtils::HashProperty(SplitStyle(), TerminalArgs(), SplitMode(), SplitSize());
|
||||
return ::Microsoft::Terminal::Settings::Model::HashUtils::HashProperty(SplitDirection(), TerminalArgs(), SplitMode(), SplitSize());
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1417,7 +1417,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
|||
}
|
||||
Json::Value json{ Json::ValueType::objectValue };
|
||||
const auto args{ get_self<FindMatchArgs>(val) };
|
||||
JsonUtils::GetValueForKey(json, DirectionKey, args->_Direction);
|
||||
JsonUtils::SetValueForKey(json, DirectionKey, args->_Direction);
|
||||
return json;
|
||||
}
|
||||
IActionArgs Copy() const
|
||||
|
|
|
@ -41,12 +41,13 @@ namespace Microsoft.Terminal.Settings.Model
|
|||
First
|
||||
};
|
||||
|
||||
enum SplitState
|
||||
enum SplitDirection
|
||||
{
|
||||
Automatic = -1,
|
||||
None = 0,
|
||||
Vertical = 1,
|
||||
Horizontal = 2
|
||||
Automatic = 0,
|
||||
Up,
|
||||
Right,
|
||||
Down,
|
||||
Left
|
||||
};
|
||||
|
||||
enum SplitType
|
||||
|
@ -187,12 +188,12 @@ namespace Microsoft.Terminal.Settings.Model
|
|||
|
||||
[default_interface] runtimeclass SplitPaneArgs : IActionArgs
|
||||
{
|
||||
SplitPaneArgs(SplitType splitMode, SplitState split, Double size, NewTerminalArgs terminalArgs);
|
||||
SplitPaneArgs(SplitState split, Double size, NewTerminalArgs terminalArgs);
|
||||
SplitPaneArgs(SplitState split, NewTerminalArgs terminalArgs);
|
||||
SplitPaneArgs(SplitType splitMode, SplitDirection split, Double size, NewTerminalArgs terminalArgs);
|
||||
SplitPaneArgs(SplitDirection split, Double size, NewTerminalArgs terminalArgs);
|
||||
SplitPaneArgs(SplitDirection split, NewTerminalArgs terminalArgs);
|
||||
SplitPaneArgs(SplitType splitMode);
|
||||
|
||||
SplitState SplitStyle { get; };
|
||||
SplitDirection SplitDirection { get; };
|
||||
NewTerminalArgs TerminalArgs { get; };
|
||||
SplitType SplitMode { get; };
|
||||
Double SplitSize { get; };
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#include "pch.h"
|
||||
#include "BaseVisualStudioGenerator.h"
|
||||
#include "DefaultProfileUtils.h"
|
||||
|
||||
using namespace Microsoft::Terminal::Settings::Model;
|
||||
using namespace winrt::Microsoft::Terminal::Settings::Model;
|
||||
|
||||
std::vector<Profile> BaseVisualStudioGenerator::GenerateProfiles()
|
||||
{
|
||||
std::vector<Profile> profiles;
|
||||
|
||||
// There's no point in enumerating valid Visual Studio instances more than once,
|
||||
// so cache them for use by both Visual Studio profile generators.
|
||||
static const auto instances = VsSetupConfiguration::QueryInstances();
|
||||
|
||||
for (auto const& instance : instances)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!IsInstanceValid(instance))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
auto DevShell{ CreateProfile(GetProfileGuidSeed(instance)) };
|
||||
DevShell.Name(GetProfileName(instance));
|
||||
DevShell.Commandline(GetProfileCommandLine(instance));
|
||||
DevShell.StartingDirectory(instance.GetInstallationPath());
|
||||
DevShell.Icon(GetProfileIconPath());
|
||||
|
||||
profiles.emplace_back(DevShell);
|
||||
}
|
||||
CATCH_LOG();
|
||||
}
|
||||
|
||||
return profiles;
|
||||
}
|
||||
|
||||
Profile BaseVisualStudioGenerator::CreateProfile(const std::wstring_view seed)
|
||||
{
|
||||
const winrt::guid profileGuid{ Microsoft::Console::Utils::CreateV5Uuid(TERMINAL_PROFILE_NAMESPACE_GUID,
|
||||
gsl::as_bytes(gsl::make_span(seed))) };
|
||||
|
||||
auto newProfile = winrt::make_self<implementation::Profile>(profileGuid);
|
||||
newProfile->Origin(OriginTag::Generated);
|
||||
|
||||
return *newProfile;
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
/*++
|
||||
Copyright (c) Microsoft Corporation
|
||||
Licensed under the MIT license.
|
||||
|
||||
Module Name:
|
||||
- BaseVisualStudioGenerator
|
||||
|
||||
Abstract:
|
||||
- Base generator for Visual Studio Developer shell profiles
|
||||
|
||||
Author(s):
|
||||
- Charles Willis - October 2020
|
||||
|
||||
--*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "IDynamicProfileGenerator.h"
|
||||
#include "VsSetupConfiguration.h"
|
||||
|
||||
namespace Microsoft::Terminal::Settings::Model
|
||||
{
|
||||
class BaseVisualStudioGenerator : public IDynamicProfileGenerator
|
||||
{
|
||||
public:
|
||||
// Inherited via IDynamicProfileGenerator
|
||||
std::wstring_view GetNamespace() override = 0;
|
||||
std::vector<winrt::Microsoft::Terminal::Settings::Model::Profile> GenerateProfiles() override;
|
||||
|
||||
protected:
|
||||
virtual bool IsInstanceValid(const VsSetupConfiguration::VsSetupInstance& instance) const = 0;
|
||||
virtual std::wstring GetProfileName(const VsSetupConfiguration::VsSetupInstance& instance) const = 0;
|
||||
virtual std::wstring GetProfileCommandLine(const VsSetupConfiguration::VsSetupInstance& instance) const = 0;
|
||||
virtual std::wstring GetProfileGuidSeed(const VsSetupConfiguration::VsSetupInstance& instance) const = 0;
|
||||
virtual std::wstring GetProfileIconPath() const = 0;
|
||||
|
||||
private:
|
||||
winrt::Microsoft::Terminal::Settings::Model::Profile CreateProfile(const std::wstring_view instanceId);
|
||||
};
|
||||
};
|
|
@ -9,6 +9,8 @@
|
|||
|
||||
#include "AzureCloudShellGenerator.h"
|
||||
#include "PowershellCoreProfileGenerator.h"
|
||||
#include "VsDevCmdGenerator.h"
|
||||
#include "VsDevShellGenerator.h"
|
||||
#include "WslDistroGenerator.h"
|
||||
|
||||
using namespace ::Microsoft::Terminal::Settings::Model;
|
||||
|
@ -51,6 +53,8 @@ CascadiaSettings::CascadiaSettings(const bool addDynamicProfiles) :
|
|||
_profileGenerators.emplace_back(std::make_unique<PowershellCoreProfileGenerator>());
|
||||
_profileGenerators.emplace_back(std::make_unique<WslDistroGenerator>());
|
||||
_profileGenerators.emplace_back(std::make_unique<AzureCloudShellGenerator>());
|
||||
_profileGenerators.emplace_back(std::make_unique<VsDevCmdGenerator>());
|
||||
_profileGenerators.emplace_back(std::make_unique<VsDevShellGenerator>());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -50,8 +50,8 @@ static constexpr std::string_view StartupActionsKey{ "startupActions" };
|
|||
static constexpr std::string_view FocusFollowMouseKey{ "focusFollowMouse" };
|
||||
static constexpr std::string_view WindowingBehaviorKey{ "windowingBehavior" };
|
||||
static constexpr std::string_view TrimBlockSelectionKey{ "trimBlockSelection" };
|
||||
static constexpr std::string_view AlwaysShowTrayIconKey{ "alwaysShowTrayIcon" };
|
||||
static constexpr std::string_view MinimizeToTrayKey{ "minimizeToTray" };
|
||||
static constexpr std::string_view AlwaysShowNotificationIconKey{ "alwaysShowNotificationIcon" };
|
||||
static constexpr std::string_view MinimizeToNotificationAreaKey{ "minimizeToNotificationArea" };
|
||||
|
||||
static constexpr std::string_view DebugFeaturesKey{ "debugFeatures" };
|
||||
|
||||
|
@ -135,8 +135,8 @@ winrt::com_ptr<GlobalAppSettings> GlobalAppSettings::Copy() const
|
|||
globals->_WindowingBehavior = _WindowingBehavior;
|
||||
globals->_TrimBlockSelection = _TrimBlockSelection;
|
||||
globals->_DetectURLs = _DetectURLs;
|
||||
globals->_MinimizeToTray = _MinimizeToTray;
|
||||
globals->_AlwaysShowTrayIcon = _AlwaysShowTrayIcon;
|
||||
globals->_MinimizeToNotificationArea = _MinimizeToNotificationArea;
|
||||
globals->_AlwaysShowNotificationIcon = _AlwaysShowNotificationIcon;
|
||||
|
||||
globals->_UnparsedDefaultProfile = _UnparsedDefaultProfile;
|
||||
globals->_validDefaultProfile = _validDefaultProfile;
|
||||
|
@ -331,9 +331,9 @@ void GlobalAppSettings::LayerJson(const Json::Value& json)
|
|||
|
||||
JsonUtils::GetValueForKey(json, DetectURLsKey, _DetectURLs);
|
||||
|
||||
JsonUtils::GetValueForKey(json, MinimizeToTrayKey, _MinimizeToTray);
|
||||
JsonUtils::GetValueForKey(json, MinimizeToNotificationAreaKey, _MinimizeToNotificationArea);
|
||||
|
||||
JsonUtils::GetValueForKey(json, AlwaysShowTrayIconKey, _AlwaysShowTrayIcon);
|
||||
JsonUtils::GetValueForKey(json, AlwaysShowNotificationIconKey, _AlwaysShowNotificationIcon);
|
||||
|
||||
// This is a helper lambda to get the keybindings and commands out of both
|
||||
// and array of objects. We'll use this twice, once on the legacy
|
||||
|
@ -432,8 +432,8 @@ Json::Value GlobalAppSettings::ToJson() const
|
|||
JsonUtils::SetValueForKey(json, WindowingBehaviorKey, _WindowingBehavior);
|
||||
JsonUtils::SetValueForKey(json, TrimBlockSelectionKey, _TrimBlockSelection);
|
||||
JsonUtils::SetValueForKey(json, DetectURLsKey, _DetectURLs);
|
||||
JsonUtils::SetValueForKey(json, MinimizeToTrayKey, _MinimizeToTray);
|
||||
JsonUtils::SetValueForKey(json, AlwaysShowTrayIconKey, _AlwaysShowTrayIcon);
|
||||
JsonUtils::SetValueForKey(json, MinimizeToNotificationAreaKey, _MinimizeToNotificationArea);
|
||||
JsonUtils::SetValueForKey(json, AlwaysShowNotificationIconKey, _AlwaysShowNotificationIcon);
|
||||
// clang-format on
|
||||
|
||||
json[JsonKey(ActionsKey)] = _actionMap->ToJson();
|
||||
|
|
|
@ -100,8 +100,8 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
|||
INHERITABLE_SETTING(Model::GlobalAppSettings, Model::WindowingMode, WindowingBehavior, Model::WindowingMode::UseNew);
|
||||
INHERITABLE_SETTING(Model::GlobalAppSettings, bool, TrimBlockSelection, false);
|
||||
INHERITABLE_SETTING(Model::GlobalAppSettings, bool, DetectURLs, true);
|
||||
INHERITABLE_SETTING(Model::GlobalAppSettings, bool, MinimizeToTray, false);
|
||||
INHERITABLE_SETTING(Model::GlobalAppSettings, bool, AlwaysShowTrayIcon, false);
|
||||
INHERITABLE_SETTING(Model::GlobalAppSettings, bool, MinimizeToNotificationArea, false);
|
||||
INHERITABLE_SETTING(Model::GlobalAppSettings, bool, AlwaysShowNotificationIcon, false);
|
||||
|
||||
private:
|
||||
guid _defaultProfile;
|
||||
|
|
|
@ -81,8 +81,8 @@ namespace Microsoft.Terminal.Settings.Model
|
|||
INHERITABLE_SETTING(WindowingMode, WindowingBehavior);
|
||||
INHERITABLE_SETTING(Boolean, TrimBlockSelection);
|
||||
INHERITABLE_SETTING(Boolean, DetectURLs);
|
||||
INHERITABLE_SETTING(Boolean, MinimizeToTray);
|
||||
INHERITABLE_SETTING(Boolean, AlwaysShowTrayIcon);
|
||||
INHERITABLE_SETTING(Boolean, MinimizeToNotificationArea);
|
||||
INHERITABLE_SETTING(Boolean, AlwaysShowNotificationIcon);
|
||||
|
||||
Windows.Foundation.Collections.IMapView<String, ColorScheme> ColorSchemes();
|
||||
void AddColorScheme(ColorScheme scheme);
|
||||
|
|
|
@ -12,9 +12,9 @@
|
|||
</PropertyGroup>
|
||||
<Import Project="..\..\..\common.openconsole.props" Condition="'$(OpenConsoleDir)'==''" />
|
||||
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.pre.props" />
|
||||
|
||||
<!-- ========================= Headers ======================== -->
|
||||
<ItemGroup>
|
||||
<ClInclude Include="BaseVisualStudioGenerator.h" />
|
||||
<ClInclude Include="DefaultTerminal.h">
|
||||
<DependentUpon>DefaultTerminal.idl</DependentUpon>
|
||||
</ClInclude>
|
||||
|
@ -78,10 +78,14 @@
|
|||
<ClInclude Include="TerminalWarnings.h">
|
||||
<DependentUpon>TerminalWarnings.idl</DependentUpon>
|
||||
</ClInclude>
|
||||
<ClInclude Include="VsDevCmdGenerator.h" />
|
||||
<ClInclude Include="VsDevShellGenerator.h" />
|
||||
<ClInclude Include="VsSetupConfiguration.h" />
|
||||
<ClInclude Include="WslDistroGenerator.h" />
|
||||
</ItemGroup>
|
||||
<!-- ========================= Cpp Files ======================== -->
|
||||
<ItemGroup>
|
||||
<ClCompile Include="BaseVisualStudioGenerator.cpp" />
|
||||
<ClCompile Include="DefaultTerminal.cpp">
|
||||
<DependentUpon>DefaultTerminal.idl</DependentUpon>
|
||||
</ClCompile>
|
||||
|
@ -145,6 +149,9 @@
|
|||
<ClCompile Include="EnumMappings.cpp">
|
||||
<DependentUpon>EnumMappings.idl</DependentUpon>
|
||||
</ClCompile>
|
||||
<ClCompile Include="VsDevCmdGenerator.cpp" />
|
||||
<ClCompile Include="VsDevShellGenerator.cpp" />
|
||||
<ClCompile Include="VsSetupConfiguration.cpp" />
|
||||
<ClCompile Include="WslDistroGenerator.cpp" />
|
||||
<!-- You _NEED_ to include this file and the jsoncpp IncludePath (below) if
|
||||
you want to use jsoncpp -->
|
||||
|
@ -236,13 +243,13 @@
|
|||
</ItemDefinitionGroup>
|
||||
<!-- ========================= Globals ======================== -->
|
||||
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.post.props" />
|
||||
|
||||
<Import Project="..\..\..\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets" Condition="Exists('..\..\..\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets')" />
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('$(OpenConsoleDir)\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(OpenConsoleDir)\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets'))" />
|
||||
<Error Condition="!Exists('..\..\..\packages\Microsoft.VisualStudio.Setup.Configuration.Native.2.3.2262\build\native\Microsoft.VisualStudio.Setup.Configuration.Native.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.VisualStudio.Setup.Configuration.Native.2.3.2262\build\native\Microsoft.VisualStudio.Setup.Configuration.Native.targets'))" />
|
||||
</Target>
|
||||
<!-- This target will take our defaults.json and stamp it into a .h file that
|
||||
we can include in the code directly. This way, we don't need to worry about
|
||||
|
@ -258,6 +265,6 @@
|
|||
<Target Name="_TerminalAppGenerateUserSettingsH" Inputs="userDefaults.json" Outputs="Generated Files\userDefaults.h" BeforeTargets="BeforeClCompile">
|
||||
<Exec Command="powershell.exe -noprofile –ExecutionPolicy Unrestricted $(OpenConsoleDir)\tools\GenerateHeaderForJson.ps1 -JsonFile userDefaults.json -OutPath '"Generated Files\userDefaults.h"' -VariableName UserSettingsJson" />
|
||||
</Target>
|
||||
|
||||
<Import Project="$(SolutionDir)build\rules\CollectWildcardResources.targets" />
|
||||
</Project>
|
||||
<Import Project="..\..\..\packages\Microsoft.VisualStudio.Setup.Configuration.Native.2.3.2262\build\native\Microsoft.VisualStudio.Setup.Configuration.Native.targets" Condition="Exists('..\..\..\packages\Microsoft.VisualStudio.Setup.Configuration.Native.2.3.2262\build\native\Microsoft.VisualStudio.Setup.Configuration.Native.targets')" />
|
||||
</Project>
|
|
@ -34,6 +34,18 @@
|
|||
<ClCompile Include="IconPathConverter.cpp" />
|
||||
<ClCompile Include="DefaultTerminal.cpp" />
|
||||
<ClCompile Include="FileUtils.cpp" />
|
||||
<ClCompile Include="BaseVisualStudioGenerator.cpp">
|
||||
<Filter>profileGeneration</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="VsDevCmdGenerator.cpp">
|
||||
<Filter>profileGeneration</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="VsDevShellGenerator.cpp">
|
||||
<Filter>profileGeneration</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="VsSetupConfiguration.cpp">
|
||||
<Filter>profileGeneration</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="pch.h" />
|
||||
|
@ -68,6 +80,18 @@
|
|||
<ClInclude Include="DefaultTerminal.h" />
|
||||
<ClInclude Include="FileUtils.h" />
|
||||
<ClInclude Include="HashUtils.h" />
|
||||
<ClInclude Include="BaseVisualStudioGenerator.h">
|
||||
<Filter>profileGeneration</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="VsDevCmdGenerator.h">
|
||||
<Filter>profileGeneration</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="VsDevShellGenerator.h">
|
||||
<Filter>profileGeneration</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="VsSetupConfiguration.h">
|
||||
<Filter>profileGeneration</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Midl Include="ActionArgs.idl" />
|
||||
|
|
|
@ -469,9 +469,6 @@
|
|||
<value>Windows Console Host</value>
|
||||
<comment>Name describing the usage of the classic windows console as the terminal UI. (`conhost.exe`)</comment>
|
||||
</data>
|
||||
<data name="MinimizeToTrayCommandKey" xml:space="preserve">
|
||||
<value>Minimize current window to tray</value>
|
||||
</data>
|
||||
<data name="QuitCommandKey" xml:space="preserve">
|
||||
<value>Quit the Terminal</value>
|
||||
</data>
|
||||
|
|
|
@ -369,12 +369,16 @@ JSON_ENUM_MAPPER(::winrt::Microsoft::Terminal::Settings::Model::ResizeDirection)
|
|||
};
|
||||
|
||||
// Possible SplitState values
|
||||
JSON_ENUM_MAPPER(::winrt::Microsoft::Terminal::Settings::Model::SplitState)
|
||||
JSON_ENUM_MAPPER(::winrt::Microsoft::Terminal::Settings::Model::SplitDirection)
|
||||
{
|
||||
JSON_MAPPINGS(3) = {
|
||||
pair_type{ "vertical", ValueType::Vertical },
|
||||
pair_type{ "horizontal", ValueType::Horizontal },
|
||||
JSON_MAPPINGS(7) = {
|
||||
pair_type{ "auto", ValueType::Automatic },
|
||||
pair_type{ "up", ValueType::Up },
|
||||
pair_type{ "right", ValueType::Right },
|
||||
pair_type{ "down", ValueType::Down },
|
||||
pair_type{ "left", ValueType::Left },
|
||||
pair_type{ "vertical", ValueType::Right },
|
||||
pair_type{ "horizontal", ValueType::Down },
|
||||
};
|
||||
};
|
||||
|
||||
|
|
21
src/cascadia/TerminalSettingsModel/VsDevCmdGenerator.cpp
Normal file
21
src/cascadia/TerminalSettingsModel/VsDevCmdGenerator.cpp
Normal file
|
@ -0,0 +1,21 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#include "pch.h"
|
||||
#include "VsDevCmdGenerator.h"
|
||||
|
||||
using namespace Microsoft::Terminal::Settings::Model;
|
||||
|
||||
std::wstring VsDevCmdGenerator::GetProfileName(const VsSetupConfiguration::VsSetupInstance& instance) const
|
||||
{
|
||||
std::wstring name{ L"Developer Command Prompt for VS " };
|
||||
name.append(instance.GetProfileNameSuffix());
|
||||
return name;
|
||||
}
|
||||
|
||||
std::wstring VsDevCmdGenerator::GetProfileCommandLine(const VsSetupConfiguration::VsSetupInstance& instance) const
|
||||
{
|
||||
std::wstring commandLine{ L"cmd.exe /k \"" + instance.GetDevCmdScriptPath() + L"\"" };
|
||||
|
||||
return commandLine;
|
||||
}
|
50
src/cascadia/TerminalSettingsModel/VsDevCmdGenerator.h
Normal file
50
src/cascadia/TerminalSettingsModel/VsDevCmdGenerator.h
Normal file
|
@ -0,0 +1,50 @@
|
|||
/*++
|
||||
Copyright (c) Microsoft Corporation
|
||||
Licensed under the MIT license.
|
||||
|
||||
Module Name:
|
||||
- VsDevCmdGenerator
|
||||
|
||||
Abstract:
|
||||
- Dynamic profile generator for Visual Studio Developer Command Prompt
|
||||
|
||||
Author(s):
|
||||
- Charles Willis - October 2020
|
||||
|
||||
--*/
|
||||
|
||||
#pragma once
|
||||
#include "BaseVisualStudioGenerator.h"
|
||||
|
||||
namespace Microsoft::Terminal::Settings::Model
|
||||
{
|
||||
class VsDevCmdGenerator : public BaseVisualStudioGenerator
|
||||
{
|
||||
public:
|
||||
std::wstring_view GetNamespace() override
|
||||
{
|
||||
return std::wstring_view{ L"Windows.Terminal.VisualStudio.CommandPrompt" };
|
||||
}
|
||||
|
||||
bool IsInstanceValid(const VsSetupConfiguration::VsSetupInstance&) const override
|
||||
{
|
||||
// We only support version of VS from 15.0.
|
||||
// Per heaths: The [ISetupConfiguration] COM server only supports Visual Studio 15.0 and newer anyway.
|
||||
// Eliding the version range will improve the discovery performance by not having to parse or compare the versions.
|
||||
return true;
|
||||
}
|
||||
|
||||
std::wstring GetProfileGuidSeed(const VsSetupConfiguration::VsSetupInstance& instance) const override
|
||||
{
|
||||
return L"VsDevCmd" + instance.GetInstanceId();
|
||||
}
|
||||
|
||||
std::wstring GetProfileIconPath() const override
|
||||
{
|
||||
return L"ms-appx:///ProfileIcons/{0caa0dad-35be-5f56-a8ff-afceeeaa6101}.png";
|
||||
}
|
||||
|
||||
std::wstring GetProfileName(const VsSetupConfiguration::VsSetupInstance& instance) const override;
|
||||
std::wstring GetProfileCommandLine(const VsSetupConfiguration::VsSetupInstance& instance) const override;
|
||||
};
|
||||
};
|
28
src/cascadia/TerminalSettingsModel/VsDevShellGenerator.cpp
Normal file
28
src/cascadia/TerminalSettingsModel/VsDevShellGenerator.cpp
Normal file
|
@ -0,0 +1,28 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#include "pch.h"
|
||||
#include "VsDevShellGenerator.h"
|
||||
#include "VsSetupConfiguration.h"
|
||||
|
||||
using namespace Microsoft::Terminal::Settings::Model;
|
||||
|
||||
std::wstring VsDevShellGenerator::GetProfileName(const VsSetupConfiguration::VsSetupInstance& instance) const
|
||||
{
|
||||
std::wstring name{ L"Developer PowerShell for VS " };
|
||||
name.append(instance.GetProfileNameSuffix());
|
||||
return name;
|
||||
}
|
||||
|
||||
std::wstring VsDevShellGenerator::GetProfileCommandLine(const VsSetupConfiguration::VsSetupInstance& instance) const
|
||||
{
|
||||
// The triple-quotes are a PowerShell path escape sequence that can safely be stored in a JSON object.
|
||||
// The "SkipAutomaticLocation" parameter will prevent "Enter-VsDevShell" from automatically setting the shell path
|
||||
// so the path in the profile will be used instead.
|
||||
std::wstring commandLine{ L"powershell.exe -NoExit -Command \"& {" };
|
||||
commandLine.append(L"Import-Module \"\"\"" + instance.GetDevShellModulePath() + L"\"\"\";");
|
||||
commandLine.append(L"Enter-VsDevShell " + instance.GetInstanceId() + L" -SkipAutomaticLocation");
|
||||
commandLine.append(L"}\"");
|
||||
|
||||
return commandLine;
|
||||
}
|
47
src/cascadia/TerminalSettingsModel/VsDevShellGenerator.h
Normal file
47
src/cascadia/TerminalSettingsModel/VsDevShellGenerator.h
Normal file
|
@ -0,0 +1,47 @@
|
|||
/*++
|
||||
Copyright (c) Microsoft Corporation
|
||||
Licensed under the MIT license.
|
||||
|
||||
Module Name:
|
||||
- VsDevShellGenerator
|
||||
|
||||
Abstract:
|
||||
- Dynamic profile generator for Visual Studio Developer PowerShell
|
||||
|
||||
Author(s):
|
||||
- Charles Willis - October 2020
|
||||
|
||||
--*/
|
||||
|
||||
#pragma once
|
||||
#include "BaseVisualStudioGenerator.h"
|
||||
|
||||
namespace Microsoft::Terminal::Settings::Model
|
||||
{
|
||||
class VsDevShellGenerator : public BaseVisualStudioGenerator
|
||||
{
|
||||
public:
|
||||
std::wstring_view GetNamespace() override
|
||||
{
|
||||
return std::wstring_view{ L"Windows.Terminal.VisualStudio.Powershell" };
|
||||
}
|
||||
|
||||
bool IsInstanceValid(const VsSetupConfiguration::VsSetupInstance& instance) const override
|
||||
{
|
||||
return instance.VersionInRange(L"[16.2,)");
|
||||
}
|
||||
|
||||
std::wstring GetProfileGuidSeed(const VsSetupConfiguration::VsSetupInstance& instance) const override
|
||||
{
|
||||
return L"VsDevShell" + instance.GetInstanceId();
|
||||
}
|
||||
|
||||
std::wstring GetProfileIconPath() const override
|
||||
{
|
||||
return L"ms-appx:///ProfileIcons/{61c54bbd-c2c6-5271-96e7-009a87ff44bf}.png";
|
||||
}
|
||||
|
||||
std::wstring GetProfileName(const VsSetupConfiguration::VsSetupInstance& instance) const override;
|
||||
std::wstring GetProfileCommandLine(const VsSetupConfiguration::VsSetupInstance& instance) const override;
|
||||
};
|
||||
};
|
112
src/cascadia/TerminalSettingsModel/VsSetupConfiguration.cpp
Normal file
112
src/cascadia/TerminalSettingsModel/VsSetupConfiguration.cpp
Normal file
|
@ -0,0 +1,112 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#include "pch.h"
|
||||
#include "VsSetupConfiguration.h"
|
||||
|
||||
using namespace Microsoft::Terminal::Settings::Model;
|
||||
|
||||
std::vector<VsSetupConfiguration::VsSetupInstance> VsSetupConfiguration::QueryInstances()
|
||||
{
|
||||
std::vector<VsSetupInstance> instances;
|
||||
|
||||
// SetupConfiguration is only registered if Visual Studio is installed
|
||||
ComPtrSetupQuery pQuery{ wil::CoCreateInstanceNoThrow<SetupConfiguration, ISetupConfiguration2>() };
|
||||
if (pQuery == nullptr)
|
||||
{
|
||||
return instances;
|
||||
}
|
||||
|
||||
// Enumerate all valid instances of Visual Studio
|
||||
wil::com_ptr<IEnumSetupInstances> e;
|
||||
THROW_IF_FAILED(pQuery->EnumInstances(&e));
|
||||
|
||||
ComPtrSetupInstance rgpInstance;
|
||||
auto result = e->Next(1, &rgpInstance, nullptr);
|
||||
while (S_OK == result)
|
||||
{
|
||||
// wrap the COM pointers in a friendly interface
|
||||
instances.emplace_back(VsSetupInstance{ pQuery, rgpInstance });
|
||||
result = e->Next(1, &rgpInstance, nullptr);
|
||||
}
|
||||
|
||||
THROW_IF_FAILED(result);
|
||||
|
||||
return instances;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Takes a relative path under a Visual Studio installation and returns the absolute path.
|
||||
/// </summary>
|
||||
std::wstring VsSetupConfiguration::ResolvePath(ISetupInstance* pInst, std::wstring_view relativePath)
|
||||
{
|
||||
wil::unique_bstr bstrAbsolutePath;
|
||||
THROW_IF_FAILED(pInst->ResolvePath(relativePath.data(), &bstrAbsolutePath));
|
||||
return bstrAbsolutePath.get();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether a Visual Studio installation version falls within a specified range.
|
||||
/// The range is specified as a string, ex: "[15.0.0.0,)", "[15.0.0.0, 16.7.0.0)
|
||||
/// </summary>
|
||||
bool VsSetupConfiguration::InstallationVersionInRange(ISetupConfiguration2* pQuery, ISetupInstance* pInst, std::wstring_view range)
|
||||
{
|
||||
const auto helper = wil::com_query<ISetupHelper>(pQuery);
|
||||
|
||||
// VS versions in a string format such as "16.3.0.0" can be easily compared
|
||||
// by parsing them into 64-bit unsigned integers using the stable algorithm
|
||||
// provided by ParseVersion and ParseVersionRange
|
||||
|
||||
unsigned long long minVersion{ 0 };
|
||||
unsigned long long maxVersion{ 0 };
|
||||
THROW_IF_FAILED(helper->ParseVersionRange(range.data(), &minVersion, &maxVersion));
|
||||
|
||||
wil::unique_bstr bstrVersion;
|
||||
THROW_IF_FAILED(pInst->GetInstallationVersion(&bstrVersion));
|
||||
|
||||
unsigned long long ullVersion{ 0 };
|
||||
THROW_IF_FAILED(helper->ParseVersion(bstrVersion.get(), &ullVersion));
|
||||
|
||||
return ullVersion >= minVersion && ullVersion <= maxVersion;
|
||||
}
|
||||
|
||||
std::wstring VsSetupConfiguration::GetInstallationVersion(ISetupInstance* pInst)
|
||||
{
|
||||
wil::unique_bstr bstrInstallationVersion;
|
||||
THROW_IF_FAILED(pInst->GetInstallationVersion(&bstrInstallationVersion));
|
||||
return bstrInstallationVersion.get();
|
||||
}
|
||||
|
||||
std::wstring VsSetupConfiguration::GetInstallationPath(ISetupInstance* pInst)
|
||||
{
|
||||
wil::unique_bstr bstrInstallationPath;
|
||||
THROW_IF_FAILED(pInst->GetInstallationPath(&bstrInstallationPath));
|
||||
return bstrInstallationPath.get();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The instance id is unique for each Visual Studio installation on a system.
|
||||
/// The instance id is generated by the Visual Studio setup engine and varies from system to system.
|
||||
/// </summary>
|
||||
std::wstring VsSetupConfiguration::GetInstanceId(ISetupInstance* pInst)
|
||||
{
|
||||
wil::unique_bstr bstrInstanceId;
|
||||
THROW_IF_FAILED(pInst->GetInstanceId(&bstrInstanceId));
|
||||
return bstrInstanceId.get();
|
||||
}
|
||||
|
||||
std::wstring VsSetupConfiguration::GetStringProperty(ISetupPropertyStore* pProps, std::wstring_view name)
|
||||
{
|
||||
if (pProps == nullptr)
|
||||
{
|
||||
return std::wstring{};
|
||||
}
|
||||
|
||||
wil::unique_variant var;
|
||||
if (FAILED(pProps->GetValue(name.data(), &var)))
|
||||
{
|
||||
return std::wstring{};
|
||||
}
|
||||
|
||||
return var.bstrVal;
|
||||
}
|
234
src/cascadia/TerminalSettingsModel/VsSetupConfiguration.h
Normal file
234
src/cascadia/TerminalSettingsModel/VsSetupConfiguration.h
Normal file
|
@ -0,0 +1,234 @@
|
|||
/*++
|
||||
Copyright (c) Microsoft Corporation
|
||||
Licensed under the MIT license.
|
||||
|
||||
Module Name:
|
||||
- VsSetupConfiguration
|
||||
|
||||
Abstract:
|
||||
- Encapsulates the Visual Studio Setup Configuration COM APIs
|
||||
|
||||
Author(s):
|
||||
- Charles Willis - October 2020
|
||||
|
||||
--*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Setup.Configuration.h"
|
||||
|
||||
namespace Microsoft::Terminal::Settings::Model
|
||||
{
|
||||
/// <summary>
|
||||
/// See https://docs.microsoft.com/en-us/dotnet/api/microsoft.visualstudio.setup.configuration?view=visualstudiosdk-2019
|
||||
/// </summary>
|
||||
class VsSetupConfiguration
|
||||
{
|
||||
typedef wil::com_ptr<ISetupConfiguration2> ComPtrSetupQuery;
|
||||
typedef wil::com_ptr<ISetupHelper> ComPtrSetupHelper;
|
||||
typedef wil::com_ptr<ISetupInstance> ComPtrSetupInstance;
|
||||
typedef wil::com_ptr<ISetupInstance2> ComPtrSetupInstance2;
|
||||
typedef wil::com_ptr<ISetupPropertyStore> ComPtrPropertyStore;
|
||||
typedef wil::com_ptr<ISetupPackageReference> ComPtrPackageReference;
|
||||
typedef wil::com_ptr<ISetupInstanceCatalog> ComPtrInstanceCatalog;
|
||||
typedef ComPtrPropertyStore ComPtrCustomPropertyStore;
|
||||
typedef ComPtrPropertyStore ComPtrCatalogPropertyStore;
|
||||
|
||||
public:
|
||||
struct VsSetupInstance
|
||||
{
|
||||
std::wstring ResolvePath(std::wstring_view relativePath) const
|
||||
{
|
||||
return VsSetupConfiguration::ResolvePath(inst.get(), relativePath);
|
||||
}
|
||||
|
||||
std::wstring GetDevShellModulePath() const
|
||||
{
|
||||
// The path of Microsoft.VisualStudio.DevShell.dll changed in 16.3
|
||||
if (VersionInRange(L"[16.3,"))
|
||||
{
|
||||
return ResolvePath(L"Common7\\Tools\\Microsoft.VisualStudio.DevShell.dll");
|
||||
}
|
||||
|
||||
return ResolvePath(L"Common7\\Tools\\vsdevshell\\Microsoft.VisualStudio.DevShell.dll");
|
||||
}
|
||||
|
||||
std::wstring GetDevCmdScriptPath() const
|
||||
{
|
||||
return ResolvePath(L"Common7\\Tools\\VsDevCmd.bat");
|
||||
}
|
||||
|
||||
bool VersionInRange(std::wstring_view range) const
|
||||
{
|
||||
return InstallationVersionInRange(query.get(), inst.get(), range);
|
||||
}
|
||||
|
||||
std::wstring GetVersion() const
|
||||
{
|
||||
return GetInstallationVersion(inst.get());
|
||||
}
|
||||
|
||||
std::wstring GetInstallationPath() const
|
||||
{
|
||||
return VsSetupConfiguration::GetInstallationPath(inst.get());
|
||||
}
|
||||
|
||||
std::wstring GetInstanceId() const
|
||||
{
|
||||
return VsSetupConfiguration::GetInstanceId(inst.get());
|
||||
}
|
||||
|
||||
ComPtrPropertyStore GetInstancePropertyStore() const
|
||||
{
|
||||
ComPtrPropertyStore properties;
|
||||
inst.query_to<ISetupPropertyStore>(&properties);
|
||||
return properties;
|
||||
}
|
||||
|
||||
ComPtrCustomPropertyStore GetCustomPropertyStore() const
|
||||
{
|
||||
ComPtrSetupInstance2 instance2;
|
||||
inst.query_to<ISetupInstance2>(&instance2);
|
||||
ComPtrCustomPropertyStore properties;
|
||||
if (FAILED(instance2->GetProperties(&properties)))
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return properties;
|
||||
}
|
||||
|
||||
ComPtrCatalogPropertyStore GetCatalogPropertyStore() const
|
||||
{
|
||||
ComPtrInstanceCatalog instanceCatalog;
|
||||
inst.query_to<ISetupInstanceCatalog>(&instanceCatalog);
|
||||
ComPtrCatalogPropertyStore properties;
|
||||
if (FAILED(instanceCatalog->GetCatalogInfo(&properties)))
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return properties;
|
||||
}
|
||||
|
||||
std::wstring GetProfileNameSuffix() const
|
||||
{
|
||||
return profileNameSuffix;
|
||||
}
|
||||
|
||||
private:
|
||||
friend class VsSetupConfiguration;
|
||||
|
||||
VsSetupInstance(ComPtrSetupQuery pQuery, ComPtrSetupInstance pInstance) :
|
||||
query(std::move(pQuery)),
|
||||
inst(std::move(pInstance)),
|
||||
profileNameSuffix(BuildProfileNameSuffix())
|
||||
{
|
||||
}
|
||||
|
||||
ComPtrSetupQuery query;
|
||||
ComPtrSetupInstance inst;
|
||||
|
||||
std::wstring profileNameSuffix;
|
||||
|
||||
std::wstring BuildProfileNameSuffix() const
|
||||
{
|
||||
ComPtrCatalogPropertyStore catalogProperties = GetCatalogPropertyStore();
|
||||
if (catalogProperties != nullptr)
|
||||
{
|
||||
std::wstring suffix;
|
||||
|
||||
std::wstring productLine{ GetProductLineVersion(catalogProperties.get()) };
|
||||
suffix.append(productLine);
|
||||
|
||||
ComPtrCustomPropertyStore customProperties = GetCustomPropertyStore();
|
||||
if (customProperties != nullptr)
|
||||
{
|
||||
std::wstring nickname{ GetNickname(customProperties.get()) };
|
||||
if (!nickname.empty())
|
||||
{
|
||||
suffix.append(L" (" + nickname + L")");
|
||||
}
|
||||
else
|
||||
{
|
||||
ComPtrPropertyStore instanceProperties = GetInstancePropertyStore();
|
||||
suffix.append(GetChannelNameSuffixTag(instanceProperties.get()));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ComPtrPropertyStore instanceProperties = GetInstancePropertyStore();
|
||||
suffix.append(GetChannelNameSuffixTag(instanceProperties.get()));
|
||||
}
|
||||
|
||||
return suffix;
|
||||
}
|
||||
|
||||
return GetVersion();
|
||||
}
|
||||
|
||||
static std::wstring GetChannelNameSuffixTag(ISetupPropertyStore* instanceProperties)
|
||||
{
|
||||
std::wstring tag;
|
||||
std::wstring channelName{ GetChannelName(instanceProperties) };
|
||||
|
||||
if (channelName.empty())
|
||||
{
|
||||
return channelName;
|
||||
}
|
||||
|
||||
if (channelName != L"Release")
|
||||
{
|
||||
tag.append(L" [" + channelName + L"]");
|
||||
}
|
||||
|
||||
return tag;
|
||||
}
|
||||
|
||||
static std::wstring GetChannelId(ISetupPropertyStore* instanceProperties)
|
||||
{
|
||||
return GetStringProperty(instanceProperties, L"channelId");
|
||||
}
|
||||
|
||||
static std::wstring GetChannelName(ISetupPropertyStore* instanceProperties)
|
||||
{
|
||||
std::wstring channelId{ GetChannelId(instanceProperties) };
|
||||
if (channelId.empty())
|
||||
{
|
||||
return channelId;
|
||||
}
|
||||
|
||||
std::wstring channelName;
|
||||
|
||||
// channelId is in the format <ProductName>.<MajorVersion>.<ChannelName>
|
||||
size_t pos = channelId.rfind(L".");
|
||||
if (pos != std::wstring::npos)
|
||||
{
|
||||
channelName.append(channelId.substr(pos + 1));
|
||||
}
|
||||
|
||||
return channelName;
|
||||
}
|
||||
|
||||
static std::wstring GetNickname(ISetupPropertyStore* customProperties)
|
||||
{
|
||||
return GetStringProperty(customProperties, L"nickname");
|
||||
}
|
||||
|
||||
static std::wstring GetProductLineVersion(ISetupPropertyStore* customProperties)
|
||||
{
|
||||
return GetStringProperty(customProperties, L"productLineVersion");
|
||||
}
|
||||
};
|
||||
|
||||
static std::vector<VsSetupInstance> QueryInstances();
|
||||
|
||||
private:
|
||||
static bool InstallationVersionInRange(ISetupConfiguration2* pQuery, ISetupInstance* pInst, std::wstring_view range);
|
||||
static std::wstring ResolvePath(ISetupInstance* pInst, std::wstring_view relativePath);
|
||||
static std::wstring GetInstallationVersion(ISetupInstance* pInst);
|
||||
static std::wstring GetInstallationPath(ISetupInstance* pInst);
|
||||
static std::wstring GetInstanceId(ISetupInstance* pInst);
|
||||
static std::wstring GetStringProperty(ISetupPropertyStore* pProps, std::wstring_view name);
|
||||
};
|
||||
};
|
|
@ -29,8 +29,8 @@
|
|||
"disableAnimations": false,
|
||||
"startupActions": "",
|
||||
"focusFollowMouse": false,
|
||||
"minimizeToTray": false,
|
||||
"alwaysShowTrayIcon": false,
|
||||
"minimizeToNotificationArea": false,
|
||||
"alwaysShowNotificationIcon": false,
|
||||
|
||||
"profiles":
|
||||
[
|
||||
|
@ -337,8 +337,10 @@
|
|||
|
||||
// Pane Management
|
||||
{ "command": "closePane", "keys": "ctrl+shift+w" },
|
||||
{ "command": { "action": "splitPane", "split": "horizontal" }, "keys": "alt+shift+-" },
|
||||
{ "command": { "action": "splitPane", "split": "vertical" }, "keys": "alt+shift+plus" },
|
||||
{ "command": { "action": "splitPane", "split": "up" } },
|
||||
{ "command": { "action": "splitPane", "split": "down" }, "keys": "alt+shift+-" },
|
||||
{ "command": { "action": "splitPane", "split": "left" } },
|
||||
{ "command": { "action": "splitPane", "split": "right" }, "keys": "alt+shift+plus" },
|
||||
{ "command": { "action": "resizePane", "direction": "down" }, "keys": "alt+shift+down" },
|
||||
{ "command": { "action": "resizePane", "direction": "left" }, "keys": "alt+shift+left" },
|
||||
{ "command": { "action": "resizePane", "direction": "right" }, "keys": "alt+shift+right" },
|
||||
|
@ -393,6 +395,7 @@
|
|||
{ "command": { "action": "adjustFontSize", "delta": 1 }, "keys": "ctrl+numpad_plus" },
|
||||
{ "command": { "action": "adjustFontSize", "delta": -1 }, "keys": "ctrl+numpad_minus" },
|
||||
{ "command": "resetFontSize", "keys": "ctrl+0" },
|
||||
{ "command": "resetFontSize", "keys": "ctrl+numpad_0" },
|
||||
|
||||
// Other commands
|
||||
{
|
||||
|
@ -431,10 +434,16 @@
|
|||
"command": { "action": "splitPane", "profile": "${profile.name}", "split": "auto" }
|
||||
},
|
||||
{
|
||||
"command": { "action": "splitPane", "profile": "${profile.name}", "split": "vertical" }
|
||||
"command": { "action": "splitPane", "profile": "${profile.name}", "split": "up" }
|
||||
},
|
||||
{
|
||||
"command": { "action": "splitPane", "profile": "${profile.name}", "split": "horizontal" }
|
||||
"command": { "action": "splitPane", "profile": "${profile.name}", "split": "down" }
|
||||
},
|
||||
{
|
||||
"command": { "action": "splitPane", "profile": "${profile.name}", "split": "left" }
|
||||
},
|
||||
{
|
||||
"command": { "action": "splitPane", "profile": "${profile.name}", "split": "right" }
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Microsoft.VisualStudio.Setup.Configuration.Native" version="2.3.2262" targetFramework="native" developmentDependency="true" />
|
||||
<package id="Microsoft.Windows.CppWinRT" version="2.0.210825.3" targetFramework="native" />
|
||||
</packages>
|
||||
|
|
|
@ -73,8 +73,8 @@ namespace RemotingUnitTests
|
|||
Remoting::WindowActivatedArgs GetLastActivatedArgs() { throw winrt::hresult_error{}; }
|
||||
void RequestRename(const Remoting::RenameRequestArgs& /*args*/) { throw winrt::hresult_error{}; }
|
||||
void Summon(const Remoting::SummonWindowBehavior& /*args*/) { throw winrt::hresult_error{}; };
|
||||
void RequestShowTrayIcon() { throw winrt::hresult_error{}; };
|
||||
void RequestHideTrayIcon() { throw winrt::hresult_error{}; };
|
||||
void RequestShowNotificationIcon() { throw winrt::hresult_error{}; };
|
||||
void RequestHideNotificationIcon() { throw winrt::hresult_error{}; };
|
||||
void RequestQuitAll() { throw winrt::hresult_error{}; };
|
||||
void Quit() { throw winrt::hresult_error{}; };
|
||||
TYPED_EVENT(WindowActivated, winrt::Windows::Foundation::IInspectable, Remoting::WindowActivatedArgs);
|
||||
|
@ -83,8 +83,8 @@ namespace RemotingUnitTests
|
|||
TYPED_EVENT(DisplayWindowIdRequested, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
|
||||
TYPED_EVENT(RenameRequested, winrt::Windows::Foundation::IInspectable, Remoting::RenameRequestArgs);
|
||||
TYPED_EVENT(SummonRequested, winrt::Windows::Foundation::IInspectable, Remoting::SummonWindowBehavior);
|
||||
TYPED_EVENT(ShowTrayIconRequested, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
|
||||
TYPED_EVENT(HideTrayIconRequested, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
|
||||
TYPED_EVENT(ShowNotificationIconRequested, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
|
||||
TYPED_EVENT(HideNotificationIconRequested, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
|
||||
TYPED_EVENT(QuitAllRequested, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
|
||||
TYPED_EVENT(QuitRequested, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
|
||||
};
|
||||
|
@ -140,11 +140,16 @@ namespace RemotingUnitTests
|
|||
|
||||
TEST_METHOD(TestSummonMostRecentIsQuake);
|
||||
|
||||
TEST_METHOD(TestSummonAfterWindowClose);
|
||||
|
||||
TEST_CLASS_SETUP(ClassSetup)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
static void _closePeasant(const com_ptr<Remoting::implementation::Monarch>& m,
|
||||
const uint64_t peasantID);
|
||||
|
||||
static void _killPeasant(const com_ptr<Remoting::implementation::Monarch>& m,
|
||||
const uint64_t peasantID);
|
||||
|
||||
|
@ -164,6 +169,19 @@ namespace RemotingUnitTests
|
|||
}
|
||||
};
|
||||
|
||||
// Helper to tell the monarch that a peasant is closing, this emulates when
|
||||
// a peasant is closed normally instead of when it crashes.
|
||||
void RemotingTests::_closePeasant(const com_ptr<Remoting::implementation::Monarch>& m,
|
||||
const uint64_t peasantID)
|
||||
{
|
||||
if (peasantID <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m->SignalClose(peasantID);
|
||||
}
|
||||
|
||||
// Helper to replace the specified peasant in a monarch with a
|
||||
// "DeadPeasant", which will emulate what happens when the peasant process
|
||||
// dies.
|
||||
|
@ -2378,4 +2396,127 @@ namespace RemotingUnitTests
|
|||
}
|
||||
}
|
||||
|
||||
void RemotingTests::TestSummonAfterWindowClose()
|
||||
{
|
||||
Log::Comment(L"Test that we can summon a window on the current desktop,"
|
||||
L" when the MRU window on that desktop closes normally.");
|
||||
|
||||
const winrt::guid guid1{ Utils::GuidFromString(L"{11111111-1111-1111-1111-111111111111}") };
|
||||
const winrt::guid guid2{ Utils::GuidFromString(L"{22222222-2222-2222-2222-222222222222}") };
|
||||
|
||||
constexpr auto monarch0PID = 12345u;
|
||||
constexpr auto peasant1PID = 23456u;
|
||||
constexpr auto peasant2PID = 34567u;
|
||||
constexpr auto peasant3PID = 45678u;
|
||||
|
||||
auto m0 = make_private<Remoting::implementation::Monarch>(monarch0PID);
|
||||
auto p1 = make_private<Remoting::implementation::Peasant>(peasant1PID);
|
||||
auto p2 = make_private<Remoting::implementation::Peasant>(peasant2PID);
|
||||
auto p3 = make_private<Remoting::implementation::Peasant>(peasant3PID);
|
||||
|
||||
p1->WindowName(L"one");
|
||||
p2->WindowName(L"two");
|
||||
p3->WindowName(L"three");
|
||||
|
||||
VERIFY_ARE_EQUAL(0, p1->GetID());
|
||||
VERIFY_ARE_EQUAL(0, p2->GetID());
|
||||
VERIFY_ARE_EQUAL(0, p3->GetID());
|
||||
|
||||
m0->AddPeasant(*p1);
|
||||
m0->AddPeasant(*p2);
|
||||
m0->AddPeasant(*p3);
|
||||
|
||||
VERIFY_ARE_EQUAL(1, p1->GetID());
|
||||
VERIFY_ARE_EQUAL(2, p2->GetID());
|
||||
VERIFY_ARE_EQUAL(3, p3->GetID());
|
||||
|
||||
VERIFY_ARE_EQUAL(3u, m0->_peasants.size());
|
||||
|
||||
bool p1ExpectedToBeSummoned = false;
|
||||
bool p2ExpectedToBeSummoned = false;
|
||||
bool p3ExpectedToBeSummoned = false;
|
||||
|
||||
p1->SummonRequested([&](auto&&, auto&&) {
|
||||
Log::Comment(L"p1 summoned");
|
||||
VERIFY_IS_TRUE(p1ExpectedToBeSummoned);
|
||||
});
|
||||
p2->SummonRequested([&](auto&&, auto&&) {
|
||||
Log::Comment(L"p2 summoned");
|
||||
VERIFY_IS_TRUE(p2ExpectedToBeSummoned);
|
||||
});
|
||||
p3->SummonRequested([&](auto&&, auto&&) {
|
||||
Log::Comment(L"p3 summoned");
|
||||
VERIFY_IS_TRUE(p3ExpectedToBeSummoned);
|
||||
});
|
||||
|
||||
{
|
||||
Log::Comment(L"Activate the first peasant, first desktop");
|
||||
Remoting::WindowActivatedArgs activatedArgs{ p1->GetID(),
|
||||
p1->GetPID(), // USE PID as HWND, because these values don't _really_ matter
|
||||
guid1,
|
||||
winrt::clock().now() };
|
||||
p1->ActivateWindow(activatedArgs);
|
||||
}
|
||||
{
|
||||
Log::Comment(L"Activate the second peasant, second desktop");
|
||||
Remoting::WindowActivatedArgs activatedArgs{ p2->GetID(),
|
||||
p2->GetPID(), // USE PID as HWND, because these values don't _really_ matter
|
||||
guid2,
|
||||
winrt::clock().now() };
|
||||
p2->ActivateWindow(activatedArgs);
|
||||
}
|
||||
{
|
||||
Log::Comment(L"Activate the third peasant, first desktop");
|
||||
Remoting::WindowActivatedArgs activatedArgs{ p3->GetID(),
|
||||
p3->GetPID(), // USE PID as HWND, because these values don't _really_ matter
|
||||
guid1,
|
||||
winrt::clock().now() };
|
||||
p3->ActivateWindow(activatedArgs);
|
||||
}
|
||||
|
||||
Log::Comment(L"Create a mock IVirtualDesktopManager to handle checking if a window is on a given desktop");
|
||||
auto manager = winrt::make_self<MockDesktopManager>();
|
||||
m0->_desktopManager = manager.try_as<IVirtualDesktopManager>();
|
||||
|
||||
auto firstCallback = [&](HWND h, BOOL* result) -> HRESULT {
|
||||
Log::Comment(L"firstCallback: Checking if window is on desktop 1");
|
||||
|
||||
const uint64_t hwnd = reinterpret_cast<uint64_t>(h);
|
||||
if (hwnd == peasant1PID || hwnd == peasant3PID)
|
||||
{
|
||||
*result = true;
|
||||
}
|
||||
else if (hwnd == peasant2PID)
|
||||
{
|
||||
*result = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
VERIFY_IS_TRUE(false, L"IsWindowOnCurrentVirtualDesktop called with unexpected value");
|
||||
}
|
||||
return S_OK;
|
||||
};
|
||||
manager->pfnIsWindowOnCurrentVirtualDesktop = firstCallback;
|
||||
|
||||
Remoting::SummonWindowSelectionArgs args;
|
||||
|
||||
Log::Comment(L"Summon window three - it is the MRU on desktop 1");
|
||||
p3ExpectedToBeSummoned = true;
|
||||
args.OnCurrentDesktop(true);
|
||||
m0->SummonWindow(args);
|
||||
VERIFY_IS_TRUE(args.FoundMatch());
|
||||
|
||||
Log::Comment(L"Close window 3. Window 1 is now the MRU on desktop 1.");
|
||||
RemotingTests::_closePeasant(m0, p3->GetID());
|
||||
|
||||
Log::Comment(L"Summon window three - it is the MRU on desktop 1");
|
||||
p1ExpectedToBeSummoned = true;
|
||||
p2ExpectedToBeSummoned = false;
|
||||
p3ExpectedToBeSummoned = false;
|
||||
args.FoundMatch(false);
|
||||
args.OnCurrentDesktop(true);
|
||||
m0->SummonWindow(args);
|
||||
VERIFY_IS_TRUE(args.FoundMatch());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -63,7 +63,7 @@ AppHost::AppHost() noexcept :
|
|||
// Update our own internal state tracking if we're in quake mode or not.
|
||||
_IsQuakeWindowChanged(nullptr, nullptr);
|
||||
|
||||
_window->SetMinimizeToTrayBehavior(_logic.GetMinimizeToTray());
|
||||
_window->SetMinimizeToNotificationAreaBehavior(_logic.GetMinimizeToNotificationArea());
|
||||
|
||||
// Tell the window to callback to us when it's about to handle a WM_CREATE
|
||||
auto pfn = std::bind(&AppHost::_HandleCreateWindow,
|
||||
|
@ -335,13 +335,13 @@ void AppHost::AppTitleChanged(const winrt::Windows::Foundation::IInspectable& /*
|
|||
// - <none>
|
||||
void AppHost::LastTabClosed(const winrt::Windows::Foundation::IInspectable& /*sender*/, const winrt::TerminalApp::LastTabClosedEventArgs& /*args*/)
|
||||
{
|
||||
if (_windowManager.IsMonarch() && _trayIcon)
|
||||
if (_windowManager.IsMonarch() && _notificationIcon)
|
||||
{
|
||||
_DestroyTrayIcon();
|
||||
_DestroyNotificationIcon();
|
||||
}
|
||||
else if (_window->IsQuakeWindow())
|
||||
{
|
||||
_HideTrayIconRequested();
|
||||
_HideNotificationIconRequested();
|
||||
}
|
||||
|
||||
_window->Close();
|
||||
|
@ -678,9 +678,9 @@ void AppHost::_BecomeMonarch(const winrt::Windows::Foundation::IInspectable& /*s
|
|||
|
||||
if (_windowManager.DoesQuakeWindowExist() ||
|
||||
_window->IsQuakeWindow() ||
|
||||
(_logic.GetAlwaysShowTrayIcon() || _logic.GetMinimizeToTray()))
|
||||
(_logic.GetAlwaysShowNotificationIcon() || _logic.GetMinimizeToNotificationArea()))
|
||||
{
|
||||
_CreateTrayIcon();
|
||||
_CreateNotificationIcon();
|
||||
}
|
||||
|
||||
// Set the number of open windows (so we know if we are the last window)
|
||||
|
@ -691,8 +691,8 @@ void AppHost::_BecomeMonarch(const winrt::Windows::Foundation::IInspectable& /*s
|
|||
_windowManager.WindowClosed([this](auto&&, auto&&) { _logic.SetNumberOfOpenWindows(_windowManager.GetNumberOfPeasants()); });
|
||||
|
||||
// These events are coming from peasants that become or un-become quake windows.
|
||||
_windowManager.ShowTrayIconRequested([this](auto&&, auto&&) { _ShowTrayIconRequested(); });
|
||||
_windowManager.HideTrayIconRequested([this](auto&&, auto&&) { _HideTrayIconRequested(); });
|
||||
_windowManager.ShowNotificationIconRequested([this](auto&&, auto&&) { _ShowNotificationIconRequested(); });
|
||||
_windowManager.HideNotificationIconRequested([this](auto&&, auto&&) { _HideNotificationIconRequested(); });
|
||||
// If the monarch receives a QuitAll event it will signal this event to be
|
||||
// ran before each peasant is closed.
|
||||
_windowManager.QuitAllRequested({ this, &AppHost::_QuitAllRequested });
|
||||
|
@ -982,12 +982,12 @@ void AppHost::_HandleSettingsChanged(const winrt::Windows::Foundation::IInspecta
|
|||
{
|
||||
_setupGlobalHotkeys();
|
||||
|
||||
// If we're monarch, we need to check some conditions to show the tray icon.
|
||||
// If there's a Quake window somewhere, we'll want to keep the tray icon.
|
||||
// There's two settings - MinimizeToTray and AlwaysShowTrayIcon. If either
|
||||
// one of them are true, we want to make sure there's a tray icon.
|
||||
// If both are false, we want to remove our icon from the tray.
|
||||
// When we remove our icon from the tray, we'll also want to re-summon
|
||||
// If we're monarch, we need to check some conditions to show the notification icon.
|
||||
// If there's a Quake window somewhere, we'll want to keep the notification icon.
|
||||
// There's two settings - MinimizeToNotificationArea and AlwaysShowNotificationIcon. If either
|
||||
// one of them are true, we want to make sure there's a notification icon.
|
||||
// If both are false, we want to remove our icon from the notification area.
|
||||
// When we remove our icon from the notification area, we'll also want to re-summon
|
||||
// any hidden windows, but right now we're not keeping track of who's hidden,
|
||||
// so just summon them all. Tracking the work to do a "summon all minimized" in
|
||||
// GH#10448
|
||||
|
@ -995,36 +995,36 @@ void AppHost::_HandleSettingsChanged(const winrt::Windows::Foundation::IInspecta
|
|||
{
|
||||
if (!_windowManager.DoesQuakeWindowExist())
|
||||
{
|
||||
if (!_trayIcon && (_logic.GetMinimizeToTray() || _logic.GetAlwaysShowTrayIcon()))
|
||||
if (!_notificationIcon && (_logic.GetMinimizeToNotificationArea() || _logic.GetAlwaysShowNotificationIcon()))
|
||||
{
|
||||
_CreateTrayIcon();
|
||||
_CreateNotificationIcon();
|
||||
}
|
||||
else if (_trayIcon && !_logic.GetMinimizeToTray() && !_logic.GetAlwaysShowTrayIcon())
|
||||
else if (_notificationIcon && !_logic.GetMinimizeToNotificationArea() && !_logic.GetAlwaysShowNotificationIcon())
|
||||
{
|
||||
_windowManager.SummonAllWindows();
|
||||
_DestroyTrayIcon();
|
||||
_DestroyNotificationIcon();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_window->SetMinimizeToTrayBehavior(_logic.GetMinimizeToTray());
|
||||
_window->SetMinimizeToNotificationAreaBehavior(_logic.GetMinimizeToNotificationArea());
|
||||
}
|
||||
|
||||
void AppHost::_IsQuakeWindowChanged(const winrt::Windows::Foundation::IInspectable&,
|
||||
const winrt::Windows::Foundation::IInspectable&)
|
||||
{
|
||||
// We want the quake window to be accessible through the tray icon.
|
||||
// This means if there's a quake window _somewhere_, we want the tray icon
|
||||
// to show regardless of the tray icon settings.
|
||||
// This also means we'll need to destroy the tray icon if it was created
|
||||
// We want the quake window to be accessible through the notification icon.
|
||||
// This means if there's a quake window _somewhere_, we want the notification icon
|
||||
// to show regardless of the notification icon settings.
|
||||
// This also means we'll need to destroy the notification icon if it was created
|
||||
// specifically for the quake window. If not, it should not be destroyed.
|
||||
if (!_window->IsQuakeWindow() && _logic.IsQuakeWindow())
|
||||
{
|
||||
_ShowTrayIconRequested();
|
||||
_ShowNotificationIconRequested();
|
||||
}
|
||||
else if (_window->IsQuakeWindow() && !_logic.IsQuakeWindow())
|
||||
{
|
||||
_HideTrayIconRequested();
|
||||
_HideNotificationIconRequested();
|
||||
}
|
||||
|
||||
_window->IsQuakeWindow(_logic.IsQuakeWindow());
|
||||
|
@ -1070,81 +1070,81 @@ void AppHost::_OpenSystemMenu(const winrt::Windows::Foundation::IInspectable&,
|
|||
}
|
||||
|
||||
// Method Description:
|
||||
// - Creates a Tray Icon and hooks up its handlers
|
||||
// - Creates a Notification Icon and hooks up its handlers
|
||||
// Arguments:
|
||||
// - <none>
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void AppHost::_CreateTrayIcon()
|
||||
void AppHost::_CreateNotificationIcon()
|
||||
{
|
||||
if constexpr (Feature_TrayIcon::IsEnabled())
|
||||
if constexpr (Feature_NotificationIcon::IsEnabled())
|
||||
{
|
||||
_trayIcon = std::make_unique<TrayIcon>(_window->GetHandle());
|
||||
_notificationIcon = std::make_unique<NotificationIcon>(_window->GetHandle());
|
||||
|
||||
// Hookup the handlers, save the tokens for revoking if settings change.
|
||||
_ReAddTrayIconToken = _window->NotifyReAddTrayIcon([this]() { _trayIcon->ReAddTrayIcon(); });
|
||||
_TrayIconPressedToken = _window->NotifyTrayIconPressed([this]() { _trayIcon->TrayIconPressed(); });
|
||||
_ShowTrayContextMenuToken = _window->NotifyShowTrayContextMenu([this](til::point coord) { _trayIcon->ShowTrayContextMenu(coord, _windowManager.GetPeasantInfos()); });
|
||||
_TrayMenuItemSelectedToken = _window->NotifyTrayMenuItemSelected([this](HMENU hm, UINT idx) { _trayIcon->TrayMenuItemSelected(hm, idx); });
|
||||
_trayIcon->SummonWindowRequested([this](auto& args) { _windowManager.SummonWindow(args); });
|
||||
_ReAddNotificationIconToken = _window->NotifyReAddNotificationIcon([this]() { _notificationIcon->ReAddNotificationIcon(); });
|
||||
_NotificationIconPressedToken = _window->NotifyNotificationIconPressed([this]() { _notificationIcon->NotificationIconPressed(); });
|
||||
_ShowNotificationIconContextMenuToken = _window->NotifyShowNotificationIconContextMenu([this](til::point coord) { _notificationIcon->ShowContextMenu(coord, _windowManager.GetPeasantInfos()); });
|
||||
_NotificationIconMenuItemSelectedToken = _window->NotifyNotificationIconMenuItemSelected([this](HMENU hm, UINT idx) { _notificationIcon->MenuItemSelected(hm, idx); });
|
||||
_notificationIcon->SummonWindowRequested([this](auto& args) { _windowManager.SummonWindow(args); });
|
||||
}
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Deletes our tray icon if we have one.
|
||||
// - Deletes our notification icon if we have one.
|
||||
// Arguments:
|
||||
// - <none>
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void AppHost::_DestroyTrayIcon()
|
||||
void AppHost::_DestroyNotificationIcon()
|
||||
{
|
||||
if constexpr (Feature_TrayIcon::IsEnabled())
|
||||
if constexpr (Feature_NotificationIcon::IsEnabled())
|
||||
{
|
||||
_window->NotifyReAddTrayIcon(_ReAddTrayIconToken);
|
||||
_window->NotifyTrayIconPressed(_TrayIconPressedToken);
|
||||
_window->NotifyShowTrayContextMenu(_ShowTrayContextMenuToken);
|
||||
_window->NotifyTrayMenuItemSelected(_TrayMenuItemSelectedToken);
|
||||
_window->NotifyReAddNotificationIcon(_ReAddNotificationIconToken);
|
||||
_window->NotifyNotificationIconPressed(_NotificationIconPressedToken);
|
||||
_window->NotifyShowNotificationIconContextMenu(_ShowNotificationIconContextMenuToken);
|
||||
_window->NotifyNotificationIconMenuItemSelected(_NotificationIconMenuItemSelectedToken);
|
||||
|
||||
_trayIcon->RemoveIconFromTray();
|
||||
_trayIcon = nullptr;
|
||||
_notificationIcon->RemoveIconFromNotificationArea();
|
||||
_notificationIcon = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void AppHost::_ShowTrayIconRequested()
|
||||
void AppHost::_ShowNotificationIconRequested()
|
||||
{
|
||||
if constexpr (Feature_TrayIcon::IsEnabled())
|
||||
if constexpr (Feature_NotificationIcon::IsEnabled())
|
||||
{
|
||||
if (_windowManager.IsMonarch())
|
||||
{
|
||||
if (!_trayIcon)
|
||||
if (!_notificationIcon)
|
||||
{
|
||||
_CreateTrayIcon();
|
||||
_CreateNotificationIcon();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_windowManager.RequestShowTrayIcon();
|
||||
_windowManager.RequestShowNotificationIcon();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AppHost::_HideTrayIconRequested()
|
||||
void AppHost::_HideNotificationIconRequested()
|
||||
{
|
||||
if constexpr (Feature_TrayIcon::IsEnabled())
|
||||
if constexpr (Feature_NotificationIcon::IsEnabled())
|
||||
{
|
||||
if (_windowManager.IsMonarch())
|
||||
{
|
||||
// Destroy it only if our settings allow it
|
||||
if (_trayIcon &&
|
||||
!_logic.GetAlwaysShowTrayIcon() &&
|
||||
!_logic.GetMinimizeToTray())
|
||||
if (_notificationIcon &&
|
||||
!_logic.GetAlwaysShowNotificationIcon() &&
|
||||
!_logic.GetMinimizeToNotificationArea())
|
||||
{
|
||||
_DestroyTrayIcon();
|
||||
_DestroyNotificationIcon();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_windowManager.RequestHideTrayIcon();
|
||||
_windowManager.RequestHideNotificationIcon();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
#include "pch.h"
|
||||
#include "NonClientIslandWindow.h"
|
||||
#include "TrayIcon.h"
|
||||
#include "NotificationIcon.h"
|
||||
|
||||
class AppHost
|
||||
{
|
||||
|
@ -97,13 +97,13 @@ private:
|
|||
void _QuitAllRequested(const winrt::Windows::Foundation::IInspectable& sender,
|
||||
const winrt::Windows::Foundation::IInspectable& args);
|
||||
|
||||
void _CreateTrayIcon();
|
||||
void _DestroyTrayIcon();
|
||||
void _ShowTrayIconRequested();
|
||||
void _HideTrayIconRequested();
|
||||
std::unique_ptr<TrayIcon> _trayIcon;
|
||||
winrt::event_token _ReAddTrayIconToken;
|
||||
winrt::event_token _TrayIconPressedToken;
|
||||
winrt::event_token _ShowTrayContextMenuToken;
|
||||
winrt::event_token _TrayMenuItemSelectedToken;
|
||||
void _CreateNotificationIcon();
|
||||
void _DestroyNotificationIcon();
|
||||
void _ShowNotificationIconRequested();
|
||||
void _HideNotificationIconRequested();
|
||||
std::unique_ptr<NotificationIcon> _notificationIcon;
|
||||
winrt::event_token _ReAddNotificationIconToken;
|
||||
winrt::event_token _NotificationIconPressedToken;
|
||||
winrt::event_token _ShowNotificationIconContextMenuToken;
|
||||
winrt::event_token _NotificationIconMenuItemSelectedToken;
|
||||
};
|
||||
|
|
|
@ -5,4 +5,4 @@
|
|||
|
||||
// Custom window messages
|
||||
#define CM_UPDATE_TITLE (WM_USER)
|
||||
#define CM_NOTIFY_FROM_TRAY (WM_USER + 1)
|
||||
#define CM_NOTIFY_FROM_NOTIFICATION_AREA (WM_USER + 1)
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
#include "../types/inc/Viewport.hpp"
|
||||
#include "resource.h"
|
||||
#include "icon.h"
|
||||
#include "TrayIcon.h"
|
||||
#include "NotificationIcon.h"
|
||||
|
||||
extern "C" IMAGE_DOS_HEADER __ImageBase;
|
||||
|
||||
|
@ -570,20 +570,20 @@ long IslandWindow::_calculateTotalSize(const bool isWidth, const long clientSize
|
|||
}
|
||||
}
|
||||
}
|
||||
case CM_NOTIFY_FROM_TRAY:
|
||||
case CM_NOTIFY_FROM_NOTIFICATION_AREA:
|
||||
{
|
||||
switch (LOWORD(lparam))
|
||||
{
|
||||
case NIN_SELECT:
|
||||
case NIN_KEYSELECT:
|
||||
{
|
||||
_NotifyTrayIconPressedHandlers();
|
||||
_NotifyNotificationIconPressedHandlers();
|
||||
return 0;
|
||||
}
|
||||
case WM_CONTEXTMENU:
|
||||
{
|
||||
const til::point eventPoint{ GET_X_LPARAM(wparam), GET_Y_LPARAM(wparam) };
|
||||
_NotifyShowTrayContextMenuHandlers(eventPoint);
|
||||
_NotifyShowNotificationIconContextMenuHandlers(eventPoint);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -591,17 +591,17 @@ long IslandWindow::_calculateTotalSize(const bool isWidth, const long clientSize
|
|||
}
|
||||
case WM_MENUCOMMAND:
|
||||
{
|
||||
_NotifyTrayMenuItemSelectedHandlers((HMENU)lparam, (UINT)wparam);
|
||||
_NotifyNotificationIconMenuItemSelectedHandlers((HMENU)lparam, (UINT)wparam);
|
||||
return 0;
|
||||
}
|
||||
default:
|
||||
// We'll want to receive this message when explorer.exe restarts
|
||||
// so that we can re-add our icon to the tray.
|
||||
// so that we can re-add our icon to the notification area.
|
||||
// This unfortunately isn't a switch case because we register the
|
||||
// message at runtime.
|
||||
if (message == WM_TASKBARCREATED)
|
||||
{
|
||||
_NotifyReAddTrayIconHandlers();
|
||||
_NotifyReAddNotificationIconHandlers();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -628,7 +628,7 @@ void IslandWindow::OnResize(const UINT width, const UINT height)
|
|||
void IslandWindow::OnMinimize()
|
||||
{
|
||||
// TODO GH#1989 Stop rendering island content when the app is minimized.
|
||||
if (_minimizeToTray)
|
||||
if (_minimizeToNotificationArea)
|
||||
{
|
||||
HideWindow();
|
||||
}
|
||||
|
@ -1640,9 +1640,9 @@ void IslandWindow::HideWindow()
|
|||
ShowWindow(GetHandle(), SW_HIDE);
|
||||
}
|
||||
|
||||
void IslandWindow::SetMinimizeToTrayBehavior(bool minimizeToTray) noexcept
|
||||
void IslandWindow::SetMinimizeToNotificationAreaBehavior(bool MinimizeToNotificationArea) noexcept
|
||||
{
|
||||
_minimizeToTray = minimizeToTray;
|
||||
_minimizeToNotificationArea = MinimizeToNotificationArea;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
|
|
|
@ -49,7 +49,7 @@ public:
|
|||
|
||||
void HideWindow();
|
||||
|
||||
void SetMinimizeToTrayBehavior(bool minimizeToTray) noexcept;
|
||||
void SetMinimizeToNotificationAreaBehavior(bool MinimizeToNotificationArea) noexcept;
|
||||
|
||||
void OpenSystemMenu(const std::optional<int> mouseX, const std::optional<int> mouseY) const noexcept;
|
||||
|
||||
|
@ -58,11 +58,11 @@ public:
|
|||
WINRT_CALLBACK(MouseScrolled, winrt::delegate<void(til::point, int32_t)>);
|
||||
WINRT_CALLBACK(WindowActivated, winrt::delegate<void()>);
|
||||
WINRT_CALLBACK(HotkeyPressed, winrt::delegate<void(long)>);
|
||||
WINRT_CALLBACK(NotifyTrayIconPressed, winrt::delegate<void()>);
|
||||
WINRT_CALLBACK(NotifyNotificationIconPressed, winrt::delegate<void()>);
|
||||
WINRT_CALLBACK(NotifyWindowHidden, winrt::delegate<void()>);
|
||||
WINRT_CALLBACK(NotifyShowTrayContextMenu, winrt::delegate<void(til::point)>);
|
||||
WINRT_CALLBACK(NotifyTrayMenuItemSelected, winrt::delegate<void(HMENU, UINT)>);
|
||||
WINRT_CALLBACK(NotifyReAddTrayIcon, winrt::delegate<void()>);
|
||||
WINRT_CALLBACK(NotifyShowNotificationIconContextMenu, winrt::delegate<void(til::point)>);
|
||||
WINRT_CALLBACK(NotifyNotificationIconMenuItemSelected, winrt::delegate<void(HMENU, UINT)>);
|
||||
WINRT_CALLBACK(NotifyReAddNotificationIcon, winrt::delegate<void()>);
|
||||
|
||||
WINRT_CALLBACK(WindowMoved, winrt::delegate<void()>);
|
||||
|
||||
|
@ -127,7 +127,7 @@ protected:
|
|||
|
||||
void _summonWindowRoutineBody(winrt::Microsoft::Terminal::Remoting::SummonWindowBehavior args);
|
||||
|
||||
bool _minimizeToTray{ false };
|
||||
bool _minimizeToNotificationArea{ false };
|
||||
|
||||
private:
|
||||
// This minimum width allows for width the tabs fit
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
#include "pch.h"
|
||||
#include "icon.h"
|
||||
#include "TrayIcon.h"
|
||||
#include "NotificationIcon.h"
|
||||
#include "CustomWindowMessages.h"
|
||||
|
||||
#include <ScopedResourceLoader.h>
|
||||
|
@ -12,54 +12,54 @@
|
|||
using namespace winrt::Windows::Foundation::Collections;
|
||||
using namespace winrt::Microsoft::Terminal;
|
||||
|
||||
TrayIcon::TrayIcon(const HWND owningHwnd) :
|
||||
NotificationIcon::NotificationIcon(const HWND owningHwnd) :
|
||||
_owningHwnd{ owningHwnd }
|
||||
{
|
||||
CreateTrayIcon();
|
||||
CreateNotificationIcon();
|
||||
}
|
||||
|
||||
TrayIcon::~TrayIcon()
|
||||
NotificationIcon::~NotificationIcon()
|
||||
{
|
||||
RemoveIconFromTray();
|
||||
RemoveIconFromNotificationArea();
|
||||
}
|
||||
|
||||
void TrayIcon::_CreateWindow()
|
||||
void NotificationIcon::_CreateWindow()
|
||||
{
|
||||
WNDCLASSW wc{};
|
||||
wc.hCursor = LoadCursor(nullptr, IDC_ARROW);
|
||||
wc.hInstance = wil::GetModuleInstanceHandle();
|
||||
wc.lpszClassName = L"TRAY_ICON_HOSTING_WINDOW_CLASS";
|
||||
wc.lpszClassName = L"NOTIFICATION_ICON_HOSTING_WINDOW_CLASS";
|
||||
wc.style = CS_HREDRAW | CS_VREDRAW;
|
||||
wc.lpfnWndProc = DefWindowProcW;
|
||||
wc.hIcon = static_cast<HICON>(GetActiveAppIconHandle(true));
|
||||
RegisterClass(&wc);
|
||||
|
||||
_trayIconHwnd = wil::unique_hwnd(CreateWindowW(wc.lpszClassName,
|
||||
wc.lpszClassName,
|
||||
WS_DISABLED,
|
||||
CW_USEDEFAULT,
|
||||
CW_USEDEFAULT,
|
||||
CW_USEDEFAULT,
|
||||
CW_USEDEFAULT,
|
||||
HWND_MESSAGE,
|
||||
nullptr,
|
||||
wc.hInstance,
|
||||
nullptr));
|
||||
_notificationIconHwnd = wil::unique_hwnd(CreateWindowW(wc.lpszClassName,
|
||||
wc.lpszClassName,
|
||||
WS_DISABLED,
|
||||
CW_USEDEFAULT,
|
||||
CW_USEDEFAULT,
|
||||
CW_USEDEFAULT,
|
||||
CW_USEDEFAULT,
|
||||
HWND_MESSAGE,
|
||||
nullptr,
|
||||
wc.hInstance,
|
||||
nullptr));
|
||||
|
||||
WINRT_VERIFY(_trayIconHwnd);
|
||||
WINRT_VERIFY(_notificationIconHwnd);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Creates and adds an icon to the notification tray.
|
||||
// - Creates and adds an icon to the notification area.
|
||||
// If an icon already exists, update the HWND associated
|
||||
// to the icon with this window's HWND.
|
||||
// Arguments:
|
||||
// - <unused>
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void TrayIcon::CreateTrayIcon()
|
||||
void NotificationIcon::CreateNotificationIcon()
|
||||
{
|
||||
if (!_trayIconHwnd)
|
||||
if (!_notificationIconHwnd)
|
||||
{
|
||||
// Creating a disabled, non visible window just so we can set it
|
||||
// as the foreground window when showing the context menu.
|
||||
|
@ -71,7 +71,7 @@ void TrayIcon::CreateTrayIcon()
|
|||
NOTIFYICONDATA nid{};
|
||||
nid.cbSize = sizeof(NOTIFYICONDATA);
|
||||
|
||||
// This HWND will receive the callbacks sent by the tray icon.
|
||||
// This HWND will receive the callbacks sent by the notification icon.
|
||||
nid.hWnd = _owningHwnd;
|
||||
|
||||
// App-defined identifier of the icon. The HWND and ID are used
|
||||
|
@ -80,7 +80,7 @@ void TrayIcon::CreateTrayIcon()
|
|||
// going to be showing one so the ID doesn't really matter.
|
||||
nid.uID = 1;
|
||||
|
||||
nid.uCallbackMessage = CM_NOTIFY_FROM_TRAY;
|
||||
nid.uCallbackMessage = CM_NOTIFY_FROM_NOTIFICATION_AREA;
|
||||
|
||||
// AppName happens to be in CascadiaPackage's Resources.
|
||||
ScopedResourceLoader loader{ L"Resources" };
|
||||
|
@ -98,7 +98,7 @@ void TrayIcon::CreateTrayIcon()
|
|||
nid.uVersion = NOTIFYICON_VERSION_4;
|
||||
Shell_NotifyIcon(NIM_SETVERSION, &nid);
|
||||
|
||||
_trayIconData = nid;
|
||||
_notificationIconData = nid;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
|
@ -109,14 +109,14 @@ void TrayIcon::CreateTrayIcon()
|
|||
// - peasants: The map of all peasants that should be available in the context menu.
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void TrayIcon::ShowTrayContextMenu(const til::point& coord,
|
||||
const IVectorView<winrt::Microsoft::Terminal::Remoting::PeasantInfo>& peasants)
|
||||
void NotificationIcon::ShowContextMenu(const til::point& coord,
|
||||
const IVectorView<winrt::Microsoft::Terminal::Remoting::PeasantInfo>& peasants)
|
||||
{
|
||||
if (const auto hMenu = _CreateTrayContextMenu(peasants))
|
||||
if (const auto hMenu = _CreateContextMenu(peasants))
|
||||
{
|
||||
// We'll need to set our window to the foreground before calling
|
||||
// TrackPopupMenuEx or else the menu won't dismiss when clicking away.
|
||||
SetForegroundWindow(_trayIconHwnd.get());
|
||||
SetForegroundWindow(_notificationIconHwnd.get());
|
||||
|
||||
// User can select menu items with the left and right buttons.
|
||||
UINT uFlags = TPM_RIGHTBUTTON;
|
||||
|
@ -137,12 +137,12 @@ void TrayIcon::ShowTrayContextMenu(const til::point& coord,
|
|||
}
|
||||
|
||||
// Method Description:
|
||||
// - This creates the context menu for our tray icon.
|
||||
// - This creates the context menu for our notification icon.
|
||||
// Arguments:
|
||||
// - peasants: A map of all peasants' ID to their window name.
|
||||
// Return Value:
|
||||
// - The handle to the newly created context menu.
|
||||
HMENU TrayIcon::_CreateTrayContextMenu(const IVectorView<winrt::Microsoft::Terminal::Remoting::PeasantInfo>& peasants)
|
||||
HMENU NotificationIcon::_CreateContextMenu(const IVectorView<winrt::Microsoft::Terminal::Remoting::PeasantInfo>& peasants)
|
||||
{
|
||||
auto hMenu = CreatePopupMenu();
|
||||
if (hMenu)
|
||||
|
@ -155,7 +155,7 @@ HMENU TrayIcon::_CreateTrayContextMenu(const IVectorView<winrt::Microsoft::Termi
|
|||
SetMenuInfo(hMenu, &mi);
|
||||
|
||||
// Focus Current Terminal Window
|
||||
AppendMenu(hMenu, MF_STRING, gsl::narrow<UINT_PTR>(TrayMenuItemAction::FocusTerminal), RS_(L"TrayIconFocusTerminal").c_str());
|
||||
AppendMenu(hMenu, MF_STRING, gsl::narrow<UINT_PTR>(NotificationIconMenuItemAction::FocusTerminal), RS_(L"NotificationIconFocusTerminal").c_str());
|
||||
AppendMenu(hMenu, MF_SEPARATOR, 0, L"");
|
||||
|
||||
// Submenu for Windows
|
||||
|
@ -183,10 +183,10 @@ HMENU TrayIcon::_CreateTrayContextMenu(const IVectorView<winrt::Microsoft::Termi
|
|||
submenuInfo.cbSize = sizeof(MENUINFO);
|
||||
submenuInfo.fMask = MIM_MENUDATA;
|
||||
submenuInfo.dwStyle = MNS_NOTIFYBYPOS;
|
||||
submenuInfo.dwMenuData = (UINT_PTR)TrayMenuItemAction::SummonWindow;
|
||||
submenuInfo.dwMenuData = (UINT_PTR)NotificationIconMenuItemAction::SummonWindow;
|
||||
SetMenuInfo(submenu, &submenuInfo);
|
||||
|
||||
AppendMenu(hMenu, MF_POPUP, (UINT_PTR)submenu, RS_(L"TrayIconWindowSubmenu").c_str());
|
||||
AppendMenu(hMenu, MF_POPUP, (UINT_PTR)submenu, RS_(L"NotificationIconWindowSubmenu").c_str());
|
||||
}
|
||||
}
|
||||
return hMenu;
|
||||
|
@ -194,13 +194,13 @@ HMENU TrayIcon::_CreateTrayContextMenu(const IVectorView<winrt::Microsoft::Termi
|
|||
|
||||
// Method Description:
|
||||
// - This is the handler for when one of the menu items are selected within
|
||||
// the tray icon's context menu.
|
||||
// the notification icon's context menu.
|
||||
// Arguments:
|
||||
// - menu: The handle to the menu that holds the menu item that was selected.
|
||||
// - menuItemIndex: The index of the menu item within the given menu.
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void TrayIcon::TrayMenuItemSelected(const HMENU menu, const UINT menuItemIndex)
|
||||
void NotificationIcon::MenuItemSelected(const HMENU menu, const UINT menuItemIndex)
|
||||
{
|
||||
// Check the menu's data for a specific action.
|
||||
MENUINFO mi{};
|
||||
|
@ -209,7 +209,7 @@ void TrayIcon::TrayMenuItemSelected(const HMENU menu, const UINT menuItemIndex)
|
|||
GetMenuInfo(menu, &mi);
|
||||
if (mi.dwMenuData)
|
||||
{
|
||||
if (gsl::narrow<TrayMenuItemAction>(mi.dwMenuData) == TrayMenuItemAction::SummonWindow)
|
||||
if (gsl::narrow<NotificationIconMenuItemAction>(mi.dwMenuData) == NotificationIconMenuItemAction::SummonWindow)
|
||||
{
|
||||
winrt::Microsoft::Terminal::Remoting::SummonWindowSelectionArgs args{};
|
||||
args.WindowID(GetMenuItemID(menu, menuItemIndex));
|
||||
|
@ -222,10 +222,10 @@ void TrayIcon::TrayMenuItemSelected(const HMENU menu, const UINT menuItemIndex)
|
|||
}
|
||||
|
||||
// Now check the menu item itself for an action.
|
||||
const auto action = gsl::narrow<TrayMenuItemAction>(GetMenuItemID(menu, menuItemIndex));
|
||||
const auto action = gsl::narrow<NotificationIconMenuItemAction>(GetMenuItemID(menu, menuItemIndex));
|
||||
switch (action)
|
||||
{
|
||||
case TrayMenuItemAction::FocusTerminal:
|
||||
case NotificationIconMenuItemAction::FocusTerminal:
|
||||
{
|
||||
winrt::Microsoft::Terminal::Remoting::SummonWindowSelectionArgs args{};
|
||||
args.SummonBehavior().ToggleVisibility(false);
|
||||
|
@ -238,12 +238,12 @@ void TrayIcon::TrayMenuItemSelected(const HMENU menu, const UINT menuItemIndex)
|
|||
}
|
||||
|
||||
// Method Description:
|
||||
// - This is the handler for when the tray icon itself is left-clicked.
|
||||
// - This is the handler for when the notification icon itself is left-clicked.
|
||||
// Arguments:
|
||||
// - <none>
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void TrayIcon::TrayIconPressed()
|
||||
void NotificationIcon::NotificationIconPressed()
|
||||
{
|
||||
// No name in the args means summon the mru window.
|
||||
winrt::Microsoft::Terminal::Remoting::SummonWindowSelectionArgs args{};
|
||||
|
@ -254,24 +254,24 @@ void TrayIcon::TrayIconPressed()
|
|||
}
|
||||
|
||||
// Method Description:
|
||||
// - Re-add a tray icon using our currently saved tray icon data.
|
||||
// - Re-add a notification icon using our currently saved notification icon data.
|
||||
// Arguments:
|
||||
// - <none>
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void TrayIcon::ReAddTrayIcon()
|
||||
void NotificationIcon::ReAddNotificationIcon()
|
||||
{
|
||||
Shell_NotifyIcon(NIM_ADD, &_trayIconData);
|
||||
Shell_NotifyIcon(NIM_SETVERSION, &_trayIconData);
|
||||
Shell_NotifyIcon(NIM_ADD, &_notificationIconData);
|
||||
Shell_NotifyIcon(NIM_SETVERSION, &_notificationIconData);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Deletes our tray icon.
|
||||
// - Deletes our notification icon.
|
||||
// Arguments:
|
||||
// - <none>
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void TrayIcon::RemoveIconFromTray()
|
||||
void NotificationIcon::RemoveIconFromNotificationArea()
|
||||
{
|
||||
Shell_NotifyIcon(NIM_DELETE, &_trayIconData);
|
||||
Shell_NotifyIcon(NIM_DELETE, &_notificationIconData);
|
||||
}
|
39
src/cascadia/WindowsTerminal/NotificationIcon.h
Normal file
39
src/cascadia/WindowsTerminal/NotificationIcon.h
Normal file
|
@ -0,0 +1,39 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#include "pch.h"
|
||||
#include "../cascadia/inc/cppwinrt_utils.h"
|
||||
|
||||
// This enumerates all the possible actions
|
||||
// that our notification icon context menu could do.
|
||||
enum class NotificationIconMenuItemAction
|
||||
{
|
||||
FocusTerminal, // Focus the MRU terminal.
|
||||
SummonWindow
|
||||
};
|
||||
|
||||
class NotificationIcon
|
||||
{
|
||||
public:
|
||||
NotificationIcon() = delete;
|
||||
NotificationIcon(const HWND owningHwnd);
|
||||
~NotificationIcon();
|
||||
|
||||
void CreateNotificationIcon();
|
||||
void RemoveIconFromNotificationArea();
|
||||
void ReAddNotificationIcon();
|
||||
|
||||
void NotificationIconPressed();
|
||||
void ShowContextMenu(const til::point& coord, const winrt::Windows::Foundation::Collections::IVectorView<winrt::Microsoft::Terminal::Remoting::PeasantInfo>& peasants);
|
||||
void MenuItemSelected(const HMENU menu, const UINT menuItemIndex);
|
||||
|
||||
WINRT_CALLBACK(SummonWindowRequested, winrt::delegate<void(winrt::Microsoft::Terminal::Remoting::SummonWindowSelectionArgs)>);
|
||||
|
||||
private:
|
||||
void _CreateWindow();
|
||||
HMENU _CreateContextMenu(const winrt::Windows::Foundation::Collections::IVectorView<winrt::Microsoft::Terminal::Remoting::PeasantInfo>& peasants);
|
||||
|
||||
wil::unique_hwnd _notificationIconHwnd;
|
||||
HWND _owningHwnd;
|
||||
NOTIFYICONDATA _notificationIconData;
|
||||
};
|
|
@ -1,39 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#include "pch.h"
|
||||
#include "../cascadia/inc/cppwinrt_utils.h"
|
||||
|
||||
// This enumerates all the possible actions
|
||||
// that our tray icon context menu could do.
|
||||
enum class TrayMenuItemAction
|
||||
{
|
||||
FocusTerminal, // Focus the MRU terminal.
|
||||
SummonWindow
|
||||
};
|
||||
|
||||
class TrayIcon
|
||||
{
|
||||
public:
|
||||
TrayIcon() = delete;
|
||||
TrayIcon(const HWND owningHwnd);
|
||||
~TrayIcon();
|
||||
|
||||
void CreateTrayIcon();
|
||||
void RemoveIconFromTray();
|
||||
void ReAddTrayIcon();
|
||||
|
||||
void TrayIconPressed();
|
||||
void ShowTrayContextMenu(const til::point& coord, const winrt::Windows::Foundation::Collections::IVectorView<winrt::Microsoft::Terminal::Remoting::PeasantInfo>& peasants);
|
||||
void TrayMenuItemSelected(const HMENU menu, const UINT menuItemIndex);
|
||||
|
||||
WINRT_CALLBACK(SummonWindowRequested, winrt::delegate<void(winrt::Microsoft::Terminal::Remoting::SummonWindowSelectionArgs)>);
|
||||
|
||||
private:
|
||||
void _CreateWindow();
|
||||
HMENU _CreateTrayContextMenu(const winrt::Windows::Foundation::Collections::IVectorView<winrt::Microsoft::Terminal::Remoting::PeasantInfo>& peasants);
|
||||
|
||||
wil::unique_hwnd _trayIconHwnd;
|
||||
HWND _owningHwnd;
|
||||
NOTIFYICONDATA _trayIconData;
|
||||
};
|
|
@ -47,7 +47,7 @@
|
|||
<ClInclude Include="CustomWindowMessages.h" />
|
||||
<ClInclude Include="IslandWindow.h" />
|
||||
<ClInclude Include="NonClientIslandWindow.h" />
|
||||
<ClInclude Include="TrayIcon.h" />
|
||||
<ClInclude Include="NotificationIcon.h" />
|
||||
<ClInclude Include="VirtualDesktopUtils.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
@ -58,7 +58,7 @@
|
|||
<ClCompile Include="AppHost.cpp" />
|
||||
<ClCompile Include="IslandWindow.cpp" />
|
||||
<ClCompile Include="NonClientIslandWindow.cpp" />
|
||||
<ClCompile Include="TrayIcon.cpp" />
|
||||
<ClCompile Include="NotificationIcon.cpp" />
|
||||
<ClCompile Include="VirtualDesktopUtils.cpp" />
|
||||
<ClCompile Include="icon.cpp" />
|
||||
</ItemGroup>
|
||||
|
|
|
@ -25,7 +25,7 @@ TRACELOGGING_DEFINE_PROVIDER(
|
|||
// !! BODGY !!
|
||||
// Manually use the resources from TerminalApp as our resources.
|
||||
// The WindowsTerminal project doesn't actually build a Resources.resw file, but
|
||||
// we still need to be able to localize strings for the tray icon menu. Anything
|
||||
// we still need to be able to localize strings for the notification icon menu. Anything
|
||||
// you want localized for WindowsTerminal.exe should be stuck in
|
||||
// ...\TerminalApp\Resources\en-US\Resources.resw
|
||||
#include <LibraryResources.h>
|
||||
|
|
|
@ -83,7 +83,8 @@
|
|||
|
||||
<!-- For ALL build types-->
|
||||
<PropertyGroup Label="Configuration">
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<PlatformToolset Condition="$(MSBuildVersion) < '17.0.0'">v142</PlatformToolset>
|
||||
<PlatformToolset Condition="$(MSBuildVersion) >= '17.0.0'">v143</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<PreferredToolArchitecture>x64</PreferredToolArchitecture>
|
||||
|
|
|
@ -65,8 +65,8 @@
|
|||
</feature>
|
||||
|
||||
<feature>
|
||||
<name>Feature_TrayIcon</name>
|
||||
<description>Controls whether the Tray Icon and related settings (aka. MinimizeToTray and AlwaysShowTrayIcon) are enabled</description>
|
||||
<name>Feature_NotificationIcon</name>
|
||||
<description>Controls whether the Notification Icon and related settings (aka. MinimizeToNotificationArea and AlwaysShowNotificationIcon) are enabled</description>
|
||||
<stage>AlwaysEnabled</stage>
|
||||
<alwaysDisabledReleaseTokens/>
|
||||
</feature>
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -349,14 +349,29 @@ class UiaTextRangeTests
|
|||
_pTextBuffer = &_pScreenInfo->GetTextBuffer();
|
||||
_pUiaData = &gci.renderData;
|
||||
|
||||
// fill text buffer with text
|
||||
for (UINT i = 0; i < _pTextBuffer->TotalRowCount(); ++i)
|
||||
// GH#6986: document end now limits the navigation to be
|
||||
// within the document end bounds _as opposed to_ the buffer bounds.
|
||||
// As a result, let's populate the buffer partially to define a document end.
|
||||
// Additionally, add spaces to create "words" in the buffer.
|
||||
|
||||
// LOAD BEARING: make sure we fill it halfway so that we can reuse most of
|
||||
// the variables from the generated tests.
|
||||
|
||||
// fill first half of text buffer with text
|
||||
for (UINT i = 0; i < _pTextBuffer->TotalRowCount() / 2; ++i)
|
||||
{
|
||||
ROW& row = _pTextBuffer->GetRowByOffset(i);
|
||||
auto& charRow = row.GetCharRow();
|
||||
for (auto& cell : charRow)
|
||||
{
|
||||
cell.Char() = L' ';
|
||||
if (i % 2 == 0)
|
||||
{
|
||||
cell.Char() = L' ';
|
||||
}
|
||||
else
|
||||
{
|
||||
cell.Char() = L'X';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -719,9 +734,13 @@ class UiaTextRangeTests
|
|||
|
||||
TEST_METHOD(CanMoveByCharacter)
|
||||
{
|
||||
const SHORT lastColumnIndex = _pScreenInfo->GetBufferSize().Width() - 1;
|
||||
const SHORT lastColumnIndex = _pScreenInfo->GetBufferSize().RightInclusive();
|
||||
const SHORT bottomRow = gsl::narrow<SHORT>(_pTextBuffer->TotalRowCount() - 1);
|
||||
|
||||
// GH#6986: This is used as the "end of the buffer" to help screen readers run faster
|
||||
// instead of parsing through thousands of empty lines of text.
|
||||
const COORD documentEnd{ _pTextBuffer->GetSize().Left(), _pTextBuffer->GetLastNonSpaceCharacter().Y + 1 };
|
||||
|
||||
// clang-format off
|
||||
const std::vector<MoveTest> testData
|
||||
{
|
||||
|
@ -749,6 +768,18 @@ class UiaTextRangeTests
|
|||
}
|
||||
},
|
||||
|
||||
MoveTest{
|
||||
L"can't move past the end of the 'document'",
|
||||
documentEnd,
|
||||
documentEnd,
|
||||
5,
|
||||
{
|
||||
0,
|
||||
documentEnd,
|
||||
documentEnd,
|
||||
}
|
||||
},
|
||||
|
||||
MoveTest{
|
||||
L"can move to a new row when necessary when moving forward",
|
||||
{ lastColumnIndex, 0 },
|
||||
|
@ -782,7 +813,7 @@ class UiaTextRangeTests
|
|||
int amountMoved;
|
||||
|
||||
THROW_IF_FAILED(Microsoft::WRL::MakeAndInitialize<UiaTextRange>(&utr, _pUiaData, &_dummyProvider, test.start, test.end));
|
||||
utr->Move(TextUnit::TextUnit_Character, test.moveAmt, &amountMoved);
|
||||
THROW_IF_FAILED(utr->Move(TextUnit::TextUnit_Character, test.moveAmt, &amountMoved));
|
||||
|
||||
VERIFY_ARE_EQUAL(test.expected.moveAmt, amountMoved);
|
||||
VERIFY_ARE_EQUAL(test.expected.start, utr->_start);
|
||||
|
@ -795,6 +826,10 @@ class UiaTextRangeTests
|
|||
const SHORT lastColumnIndex = _pScreenInfo->GetBufferSize().Width() - 1;
|
||||
const SHORT bottomRow = gsl::narrow<SHORT>(_pTextBuffer->TotalRowCount() - 1);
|
||||
|
||||
// GH#6986: This is used as the "end of the buffer" to help screen readers run faster
|
||||
// instead of parsing through thousands of empty lines of text.
|
||||
const COORD documentEnd{ _pTextBuffer->GetSize().Left(), _pTextBuffer->GetLastNonSpaceCharacter().Y + 1 };
|
||||
|
||||
// clang-format off
|
||||
const std::vector<MoveTest> testData
|
||||
{
|
||||
|
@ -810,15 +845,27 @@ class UiaTextRangeTests
|
|||
}
|
||||
},
|
||||
|
||||
MoveTest{
|
||||
L"can't move past the end of the 'document'",
|
||||
documentEnd,
|
||||
documentEnd,
|
||||
5,
|
||||
{
|
||||
0,
|
||||
documentEnd,
|
||||
documentEnd,
|
||||
}
|
||||
},
|
||||
|
||||
MoveTest{
|
||||
L"can move backward from bottom row",
|
||||
{0, bottomRow},
|
||||
{lastColumnIndex, bottomRow},
|
||||
{0, documentEnd.Y},
|
||||
{lastColumnIndex, documentEnd.Y},
|
||||
-3,
|
||||
{
|
||||
-3,
|
||||
{0, bottomRow - 3},
|
||||
{0, bottomRow - 2}
|
||||
{0, base::ClampSub(documentEnd.Y, 3)},
|
||||
{0, base::ClampSub(documentEnd.Y, 3)}
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -868,6 +915,10 @@ class UiaTextRangeTests
|
|||
const SHORT lastColumnIndex = _pScreenInfo->GetBufferSize().Width() - 1;
|
||||
const SHORT bottomRow = static_cast<SHORT>(_pTextBuffer->TotalRowCount() - 1);
|
||||
|
||||
// GH#6986: This is used as the "end of the buffer" to help screen readers run faster
|
||||
// instead of parsing through thousands of empty lines of text.
|
||||
const COORD documentEnd{ _pTextBuffer->GetSize().RightInclusive(), _pTextBuffer->GetLastNonSpaceCharacter().Y };
|
||||
|
||||
// clang-format off
|
||||
const std::vector<MoveEndpointTest> testData
|
||||
{
|
||||
|
@ -910,6 +961,19 @@ class UiaTextRangeTests
|
|||
}
|
||||
},
|
||||
|
||||
MoveEndpointTest{
|
||||
L"can't move _end past the end of the document",
|
||||
{0, 0},
|
||||
documentEnd,
|
||||
5,
|
||||
TextPatternRangeEndpoint_End,
|
||||
{
|
||||
1,
|
||||
{0,0},
|
||||
{0, base::ClampAdd(documentEnd.Y,1)}
|
||||
}
|
||||
},
|
||||
|
||||
MoveEndpointTest{
|
||||
L"_start follows _end when passed during movement",
|
||||
{5, 0},
|
||||
|
@ -925,40 +989,40 @@ class UiaTextRangeTests
|
|||
|
||||
MoveEndpointTest{
|
||||
L"can't move _end past the beginning of the document when _end is positioned at the end",
|
||||
{0, bottomRow},
|
||||
{0, bottomRow+1},
|
||||
{0, documentEnd.Y},
|
||||
{0, base::ClampAdd(documentEnd.Y,1)},
|
||||
1,
|
||||
TextPatternRangeEndpoint_End,
|
||||
{
|
||||
0,
|
||||
{0, bottomRow},
|
||||
{0, bottomRow+1},
|
||||
{0, documentEnd.Y},
|
||||
{0, base::ClampAdd(documentEnd.Y,1)},
|
||||
}
|
||||
},
|
||||
|
||||
MoveEndpointTest{
|
||||
L"can partially move _end to the end of the document when it is closer than the move count requested",
|
||||
{0, 0},
|
||||
{lastColumnIndex - 3, bottomRow},
|
||||
{base::ClampSub(lastColumnIndex, 3), documentEnd.Y},
|
||||
5,
|
||||
TextPatternRangeEndpoint_End,
|
||||
{
|
||||
4,
|
||||
{0, 0},
|
||||
{0, bottomRow+1},
|
||||
{0, base::ClampAdd(documentEnd.Y,1)},
|
||||
}
|
||||
},
|
||||
|
||||
MoveEndpointTest{
|
||||
L"can't move _start past the end of the document",
|
||||
{lastColumnIndex - 4, bottomRow},
|
||||
{0, bottomRow+1},
|
||||
{base::ClampSub(lastColumnIndex, 4), documentEnd.Y},
|
||||
{0, base::ClampAdd(documentEnd.Y,1)},
|
||||
5,
|
||||
TextPatternRangeEndpoint_Start,
|
||||
{
|
||||
5,
|
||||
{0, bottomRow+1},
|
||||
{0, bottomRow+1},
|
||||
{0, base::ClampAdd(documentEnd.Y,1)},
|
||||
{0, base::ClampAdd(documentEnd.Y,1)},
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -997,6 +1061,10 @@ class UiaTextRangeTests
|
|||
const SHORT lastColumnIndex = _pScreenInfo->GetBufferSize().Width() - 1;
|
||||
const SHORT bottomRow = gsl::narrow<SHORT>(_pTextBuffer->TotalRowCount() - 1);
|
||||
|
||||
// GH#6986: This is used as the "end of the buffer" to help screen readers run faster
|
||||
// instead of parsing through thousands of empty lines of text.
|
||||
const COORD documentEnd{ _pTextBuffer->GetSize().Left(), _pTextBuffer->GetLastNonSpaceCharacter().Y + 1 };
|
||||
|
||||
// clang-format off
|
||||
const std::vector<MoveEndpointTest> testData
|
||||
{
|
||||
|
@ -1067,36 +1135,36 @@ class UiaTextRangeTests
|
|||
},
|
||||
|
||||
MoveEndpointTest{
|
||||
L"can move _end forwards when it's on the bottom row",
|
||||
L"can't move _end forwards when it's on the bottom row (past doc end)",
|
||||
{0, 0},
|
||||
{lastColumnIndex - 3, bottomRow},
|
||||
1,
|
||||
TextPatternRangeEndpoint_End,
|
||||
1,
|
||||
0,
|
||||
{0, 0},
|
||||
{0, bottomRow+1}
|
||||
documentEnd
|
||||
},
|
||||
|
||||
MoveEndpointTest{
|
||||
L"can't move _end forwards when it's at the end of the document already",
|
||||
L"can't move _end forwards when it's at the end of the buffer already (past doc end)",
|
||||
{0, 0},
|
||||
{0, bottomRow+1},
|
||||
1,
|
||||
TextPatternRangeEndpoint_End,
|
||||
0,
|
||||
{0, 0},
|
||||
{0, bottomRow+1}
|
||||
documentEnd
|
||||
},
|
||||
|
||||
MoveEndpointTest{
|
||||
L"moving _start forward when it's already on the bottom row creates a degenerate range at the document end",
|
||||
L"moving _start forward when it's already on the bottom row (past doc end) creates a degenerate range at the document end",
|
||||
{0, bottomRow},
|
||||
{lastColumnIndex, bottomRow},
|
||||
1,
|
||||
TextPatternRangeEndpoint_Start,
|
||||
1,
|
||||
{0, bottomRow+1},
|
||||
{0, bottomRow+1}
|
||||
0,
|
||||
documentEnd,
|
||||
documentEnd
|
||||
},
|
||||
|
||||
MoveEndpointTest{
|
||||
|
@ -1132,6 +1200,10 @@ class UiaTextRangeTests
|
|||
const SHORT lastColumnIndex = _pScreenInfo->GetBufferSize().Width() - 1;
|
||||
const SHORT bottomRow = gsl::narrow<SHORT>(_pTextBuffer->TotalRowCount() - 1);
|
||||
|
||||
// GH#6986: This is used as the "end of the buffer" to help screen readers run faster
|
||||
// instead of parsing through thousands of empty lines of text.
|
||||
const COORD documentEnd{ _pTextBuffer->GetSize().Left(), _pTextBuffer->GetLastNonSpaceCharacter().Y + 1 };
|
||||
|
||||
// clang-format off
|
||||
const std::vector<MoveEndpointTest> testData =
|
||||
{
|
||||
|
@ -1144,7 +1216,7 @@ class UiaTextRangeTests
|
|||
{
|
||||
1,
|
||||
{0, 4},
|
||||
{0, bottomRow+1}
|
||||
documentEnd
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -1162,7 +1234,7 @@ class UiaTextRangeTests
|
|||
},
|
||||
|
||||
MoveEndpointTest{
|
||||
L"can't move _end forward when it's already at the end of the document",
|
||||
L"can't move _end forward when it's already at the end of the buffer (past doc end)",
|
||||
{3, 2},
|
||||
{0, bottomRow+1},
|
||||
1,
|
||||
|
@ -1170,7 +1242,7 @@ class UiaTextRangeTests
|
|||
{
|
||||
0,
|
||||
{3, 2},
|
||||
{0, bottomRow+1}
|
||||
documentEnd
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -1208,8 +1280,8 @@ class UiaTextRangeTests
|
|||
TextPatternRangeEndpoint_Start,
|
||||
{
|
||||
1,
|
||||
{0, bottomRow+1},
|
||||
{0, bottomRow+1}
|
||||
documentEnd,
|
||||
documentEnd
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -1235,51 +1307,64 @@ class UiaTextRangeTests
|
|||
// GH#7664: When attempting to expand to an enclosing unit
|
||||
// at the end exclusive, the UTR should refuse to move past
|
||||
// the end.
|
||||
const auto lastNonspaceCharPos{ _pTextBuffer->GetLastNonSpaceCharacter() };
|
||||
const COORD documentEnd{ 0, lastNonspaceCharPos.Y + 1 };
|
||||
|
||||
const til::point endInclusive{ bufferEnd };
|
||||
|
||||
// Iterate over each TextUnit. If the we don't support
|
||||
// Iterate over each TextUnit. If we don't support
|
||||
// the given TextUnit, we're supposed to fallback
|
||||
// to the last one that was defined anyways.
|
||||
BEGIN_TEST_METHOD_PROPERTIES()
|
||||
TEST_METHOD_PROPERTY(L"Data:textUnit", L"{0, 1, 2, 3, 4, 5, 6}")
|
||||
END_TEST_METHOD_PROPERTIES();
|
||||
|
||||
int textUnit;
|
||||
VERIFY_SUCCEEDED(TestData::TryGetValue(L"textUnit", textUnit), L"Get textUnit variant");
|
||||
|
||||
Microsoft::WRL::ComPtr<UiaTextRange> utr;
|
||||
for (int unit = TextUnit::TextUnit_Character; unit != TextUnit::TextUnit_Document; ++unit)
|
||||
{
|
||||
Log::Comment(NoThrowString().Format(L"%s", toString(static_cast<TextUnit>(unit))));
|
||||
Log::Comment(NoThrowString().Format(L"%s", toString(static_cast<TextUnit>(textUnit))));
|
||||
|
||||
// Create a degenerate UTR at EndExclusive
|
||||
THROW_IF_FAILED(Microsoft::WRL::MakeAndInitialize<UiaTextRange>(&utr, _pUiaData, &_dummyProvider, endInclusive, endExclusive));
|
||||
THROW_IF_FAILED(utr->ExpandToEnclosingUnit(static_cast<TextUnit>(unit)));
|
||||
// Create a degenerate UTR at EndExclusive
|
||||
THROW_IF_FAILED(Microsoft::WRL::MakeAndInitialize<UiaTextRange>(&utr, _pUiaData, &_dummyProvider, bufferEnd, endExclusive));
|
||||
THROW_IF_FAILED(utr->ExpandToEnclosingUnit(static_cast<TextUnit>(textUnit)));
|
||||
|
||||
VERIFY_ARE_EQUAL(endExclusive, til::point{ utr->_end });
|
||||
}
|
||||
VERIFY_ARE_EQUAL(documentEnd, til::point{ utr->_end });
|
||||
}
|
||||
|
||||
TEST_METHOD(MovementAtExclusiveEnd)
|
||||
{
|
||||
// GH#7663: When attempting to move from end exclusive,
|
||||
// the UTR should refuse to move past the end.
|
||||
|
||||
const auto lastLineStart{ bufferEndLeft };
|
||||
const auto secondToLastLinePos{ point_offset_by_line(lastLineStart, bufferSize, -1) };
|
||||
const auto secondToLastCharacterPos{ point_offset_by_char(bufferEnd, bufferSize, -1) };
|
||||
const auto endInclusive{ bufferEnd };
|
||||
|
||||
// write "temp" at (2,2)
|
||||
_pTextBuffer->Reset();
|
||||
const til::point writeTarget{ 2, 2 };
|
||||
_pTextBuffer->Write({ L"temp" }, writeTarget);
|
||||
|
||||
// GH#6986: This is used as the "end of the buffer" to help screen readers run faster
|
||||
// instead of parsing through thousands of empty lines of text.
|
||||
const COORD documentEndInclusive{ base::ClampSub<short, short>(static_cast<short>(bufferSize.right()), 1), _pTextBuffer->GetLastNonSpaceCharacter().Y };
|
||||
const COORD documentEndExclusive{ static_cast<short>(bufferSize.left()), base::ClampAdd(documentEndInclusive.Y, 1) };
|
||||
|
||||
const COORD lastLineStart{ static_cast<short>(bufferSize.left()), documentEndInclusive.Y };
|
||||
const auto secondToLastLinePos{ point_offset_by_line(lastLineStart, bufferSize, -1) };
|
||||
const COORD secondToLastCharacterPos{ documentEndInclusive.X - 1, documentEndInclusive.Y };
|
||||
|
||||
// Iterate over each TextUnit. If we don't support
|
||||
// the given TextUnit, we're supposed to fallback
|
||||
// to the last one that was defined anyways.
|
||||
BEGIN_TEST_METHOD_PROPERTIES()
|
||||
TEST_METHOD_PROPERTY(L"Data:textUnit", L"{0, 1, 2, 3, 4, 5, 6}")
|
||||
TEST_METHOD_PROPERTY(L"Data:degenerate", L"{false, true}")
|
||||
TEST_METHOD_PROPERTY(L"Data:atDocumentEnd", L"{false, true}")
|
||||
END_TEST_METHOD_PROPERTIES();
|
||||
|
||||
int unit;
|
||||
bool degenerate;
|
||||
bool atDocumentEnd;
|
||||
VERIFY_SUCCEEDED(TestData::TryGetValue(L"textUnit", unit), L"Get TextUnit variant");
|
||||
VERIFY_SUCCEEDED(TestData::TryGetValue(L"degenerate", degenerate), L"Get degenerate variant");
|
||||
VERIFY_SUCCEEDED(TestData::TryGetValue(L"atDocumentEnd", atDocumentEnd), L"Get atDocumentEnd variant");
|
||||
TextUnit textUnit{ static_cast<TextUnit>(unit) };
|
||||
|
||||
Microsoft::WRL::ComPtr<UiaTextRange> utr;
|
||||
|
@ -1287,17 +1372,22 @@ class UiaTextRangeTests
|
|||
Log::Comment(NoThrowString().Format(L"Forward by %s", toString(textUnit)));
|
||||
|
||||
// Create an UTR at EndExclusive
|
||||
const auto utrEnd{ atDocumentEnd ? documentEndExclusive : endExclusive };
|
||||
if (degenerate)
|
||||
{
|
||||
THROW_IF_FAILED(Microsoft::WRL::MakeAndInitialize<UiaTextRange>(&utr, _pUiaData, &_dummyProvider, endExclusive, endExclusive));
|
||||
// UTR: (exclusive, exclusive) range
|
||||
const auto utrStart{ atDocumentEnd ? documentEndExclusive : endExclusive };
|
||||
THROW_IF_FAILED(Microsoft::WRL::MakeAndInitialize<UiaTextRange>(&utr, _pUiaData, &_dummyProvider, utrStart, utrEnd));
|
||||
}
|
||||
else
|
||||
{
|
||||
THROW_IF_FAILED(Microsoft::WRL::MakeAndInitialize<UiaTextRange>(&utr, _pUiaData, &_dummyProvider, endInclusive, endExclusive));
|
||||
// UTR: (inclusive, exclusive) range
|
||||
const auto utrStart{ atDocumentEnd ? documentEndInclusive : endInclusive };
|
||||
THROW_IF_FAILED(Microsoft::WRL::MakeAndInitialize<UiaTextRange>(&utr, _pUiaData, &_dummyProvider, utrStart, utrEnd));
|
||||
}
|
||||
THROW_IF_FAILED(utr->Move(textUnit, 1, &moveAmt));
|
||||
|
||||
VERIFY_ARE_EQUAL(endExclusive, til::point{ utr->_end });
|
||||
VERIFY_ARE_EQUAL(documentEndExclusive, utr->_end);
|
||||
VERIFY_ARE_EQUAL(0, moveAmt);
|
||||
|
||||
// Verify expansion works properly
|
||||
|
@ -1305,33 +1395,35 @@ class UiaTextRangeTests
|
|||
THROW_IF_FAILED(utr->ExpandToEnclosingUnit(textUnit));
|
||||
if (textUnit <= TextUnit::TextUnit_Character)
|
||||
{
|
||||
VERIFY_ARE_EQUAL(endInclusive, til::point{ utr->_start });
|
||||
VERIFY_ARE_EQUAL(endExclusive, til::point{ utr->_end });
|
||||
VERIFY_ARE_EQUAL(documentEndInclusive, utr->_start);
|
||||
VERIFY_ARE_EQUAL(documentEndExclusive, utr->_end);
|
||||
}
|
||||
else if (textUnit <= TextUnit::TextUnit_Word)
|
||||
{
|
||||
VERIFY_ARE_EQUAL(writeTarget, til::point{ utr->_start });
|
||||
VERIFY_ARE_EQUAL(endExclusive, til::point{ utr->_end });
|
||||
VERIFY_ARE_EQUAL(documentEndExclusive, utr->_end);
|
||||
}
|
||||
else if (textUnit <= TextUnit::TextUnit_Line)
|
||||
{
|
||||
VERIFY_ARE_EQUAL(lastLineStart, til::point{ utr->_start });
|
||||
VERIFY_ARE_EQUAL(endExclusive, til::point{ utr->_end });
|
||||
VERIFY_ARE_EQUAL(lastLineStart, utr->_start);
|
||||
VERIFY_ARE_EQUAL(documentEndExclusive, utr->_end);
|
||||
}
|
||||
else // textUnit <= TextUnit::TextUnit_Document:
|
||||
{
|
||||
VERIFY_ARE_EQUAL(origin, til::point{ utr->_start });
|
||||
VERIFY_ARE_EQUAL(endExclusive, til::point{ utr->_end });
|
||||
VERIFY_ARE_EQUAL(documentEndExclusive, utr->_end);
|
||||
}
|
||||
|
||||
// reset the UTR
|
||||
if (degenerate)
|
||||
{
|
||||
THROW_IF_FAILED(Microsoft::WRL::MakeAndInitialize<UiaTextRange>(&utr, _pUiaData, &_dummyProvider, endExclusive, endExclusive));
|
||||
const auto utrStart{ atDocumentEnd ? documentEndExclusive : endExclusive };
|
||||
THROW_IF_FAILED(Microsoft::WRL::MakeAndInitialize<UiaTextRange>(&utr, _pUiaData, &_dummyProvider, utrStart, utrEnd));
|
||||
}
|
||||
else
|
||||
{
|
||||
THROW_IF_FAILED(Microsoft::WRL::MakeAndInitialize<UiaTextRange>(&utr, _pUiaData, &_dummyProvider, endInclusive, endExclusive));
|
||||
const auto utrStart{ atDocumentEnd ? documentEndInclusive : endInclusive };
|
||||
THROW_IF_FAILED(Microsoft::WRL::MakeAndInitialize<UiaTextRange>(&utr, _pUiaData, &_dummyProvider, utrStart, utrEnd));
|
||||
}
|
||||
|
||||
// Verify that moving backwards still works properly
|
||||
|
@ -1345,26 +1437,26 @@ class UiaTextRangeTests
|
|||
// - degenerate --> it moves with _start to stay degenerate
|
||||
// - !degenerate --> it excludes the last char, to select the second to last char
|
||||
VERIFY_ARE_EQUAL(-1, moveAmt);
|
||||
VERIFY_ARE_EQUAL(degenerate ? endInclusive : secondToLastCharacterPos, til::point{ utr->_start });
|
||||
VERIFY_ARE_EQUAL(endInclusive, til::point{ utr->_end });
|
||||
VERIFY_ARE_EQUAL(degenerate || !atDocumentEnd ? documentEndInclusive : secondToLastCharacterPos, utr->_start);
|
||||
VERIFY_ARE_EQUAL(documentEndInclusive, utr->_end);
|
||||
}
|
||||
else if (textUnit <= TextUnit::TextUnit_Word)
|
||||
{
|
||||
VERIFY_ARE_EQUAL(-1, moveAmt);
|
||||
VERIFY_ARE_EQUAL(origin, til::point{ utr->_start });
|
||||
VERIFY_ARE_EQUAL(degenerate ? origin : writeTarget, til::point{ utr->_end });
|
||||
VERIFY_ARE_EQUAL(degenerate || !atDocumentEnd ? origin : writeTarget, til::point{ utr->_end });
|
||||
}
|
||||
else if (textUnit <= TextUnit::TextUnit_Line)
|
||||
{
|
||||
VERIFY_ARE_EQUAL(-1, moveAmt);
|
||||
VERIFY_ARE_EQUAL(degenerate ? lastLineStart : secondToLastLinePos, til::point{ utr->_start });
|
||||
VERIFY_ARE_EQUAL(degenerate || !atDocumentEnd ? lastLineStart : secondToLastLinePos, til::point{ utr->_start });
|
||||
VERIFY_ARE_EQUAL(lastLineStart, til::point{ utr->_end });
|
||||
}
|
||||
else // textUnit <= TextUnit::TextUnit_Document:
|
||||
{
|
||||
VERIFY_ARE_EQUAL(degenerate ? -1 : 0, moveAmt);
|
||||
VERIFY_ARE_EQUAL(degenerate || !atDocumentEnd ? -1 : 0, moveAmt);
|
||||
VERIFY_ARE_EQUAL(origin, til::point{ utr->_start });
|
||||
VERIFY_ARE_EQUAL(degenerate ? origin : endExclusive, til::point{ utr->_end });
|
||||
VERIFY_ARE_EQUAL(degenerate || !atDocumentEnd ? origin : documentEndExclusive, til::point{ utr->_end });
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1829,37 +1921,38 @@ class UiaTextRangeTests
|
|||
TEST_METHOD(GeneratedMovementTests)
|
||||
{
|
||||
// Populate the buffer with...
|
||||
// - 9 segments of alternating text
|
||||
// - 10 segments of alternating text
|
||||
// - up to half of the buffer (vertically)
|
||||
// It'll look something like this
|
||||
// +---------------------------+
|
||||
// |XXX XXX XXX XXX XXX|
|
||||
// |XXX XXX XXX XXX XXX|
|
||||
// |XXX XXX XXX XXX XXX|
|
||||
// |XXX XXX XXX XXX XXX|
|
||||
// |XXX XXX XXX XXX XXX|
|
||||
// | |
|
||||
// | |
|
||||
// | |
|
||||
// | |
|
||||
// | |
|
||||
// +---------------------------+
|
||||
// +------------------------------+
|
||||
// |XXX XXX XXX XXX XXX |
|
||||
// |XXX XXX XXX XXX XXX |
|
||||
// |XXX XXX XXX XXX XXX |
|
||||
// |XXX XXX XXX XXX XXX |
|
||||
// |XXX XXX XXX XXX XXX |
|
||||
// | |
|
||||
// | |
|
||||
// | |
|
||||
// | |
|
||||
// | |
|
||||
// +------------------------------+
|
||||
{
|
||||
short i = 0;
|
||||
auto iter{ _pTextBuffer->GetCellDataAt(bufferSize.origin()) };
|
||||
const auto segment{ bufferSize.width() / 9 };
|
||||
const auto segment{ bufferSize.width() / 10 };
|
||||
bool fill{ true };
|
||||
while (iter.Pos() != docEnd)
|
||||
{
|
||||
bool fill{ true };
|
||||
if (i % segment == 0)
|
||||
if (iter.Pos().X == bufferSize.left())
|
||||
{
|
||||
fill = true;
|
||||
}
|
||||
else if (i % segment == 0)
|
||||
{
|
||||
fill = !fill;
|
||||
}
|
||||
|
||||
if (fill)
|
||||
{
|
||||
_pTextBuffer->Write({ L"X" }, iter.Pos());
|
||||
}
|
||||
_pTextBuffer->Write({ fill ? L"X" : L" " }, iter.Pos());
|
||||
|
||||
++i;
|
||||
++iter;
|
||||
|
|
|
@ -280,52 +280,50 @@ IFACEMETHODIMP UiaTextRangeBase::ExpandToEnclosingUnit(_In_ TextUnit unit) noexc
|
|||
void UiaTextRangeBase::_expandToEnclosingUnit(TextUnit unit)
|
||||
{
|
||||
const auto& buffer = _pData->GetTextBuffer();
|
||||
const auto bufferSize = _getBufferSize();
|
||||
const auto bufferEnd = bufferSize.EndExclusive();
|
||||
const auto bufferSize{ buffer.GetSize() };
|
||||
const auto documentEnd{ _getDocumentEnd() };
|
||||
|
||||
// If we're past document end,
|
||||
// set us to ONE BEFORE the document end.
|
||||
// This allows us to expand properly.
|
||||
if (bufferSize.CompareInBounds(_start, documentEnd, true) >= 0)
|
||||
{
|
||||
_start = documentEnd;
|
||||
bufferSize.DecrementInBounds(_start, true);
|
||||
}
|
||||
|
||||
if (unit == TextUnit_Character)
|
||||
{
|
||||
_start = buffer.GetGlyphStart(_start);
|
||||
_end = buffer.GetGlyphEnd(_start);
|
||||
_start = buffer.GetGlyphStart(_start, documentEnd);
|
||||
_end = buffer.GetGlyphEnd(_start, documentEnd);
|
||||
}
|
||||
else if (unit <= TextUnit_Word)
|
||||
{
|
||||
// expand to word
|
||||
_start = buffer.GetWordStart(_start, _wordDelimiters, true);
|
||||
_end = buffer.GetWordEnd(_start, _wordDelimiters, true);
|
||||
|
||||
// GetWordEnd may return the actual end of the TextBuffer.
|
||||
// If so, just set it to this value of bufferEnd
|
||||
if (!bufferSize.IsInBounds(_end))
|
||||
{
|
||||
_end = bufferEnd;
|
||||
}
|
||||
_start = buffer.GetWordStart(_start, _wordDelimiters, true, documentEnd);
|
||||
_end = buffer.GetWordEnd(_start, _wordDelimiters, true, documentEnd);
|
||||
}
|
||||
else if (unit <= TextUnit_Line)
|
||||
{
|
||||
if (_start == bufferEnd)
|
||||
// expand to line
|
||||
_start.X = 0;
|
||||
if (_start.Y == documentEnd.y())
|
||||
{
|
||||
// Special case: if we are at the bufferEnd,
|
||||
// move _start back one, instead of _end forward
|
||||
_start.X = 0;
|
||||
_start.Y = base::ClampSub(_start.Y, 1);
|
||||
_end = bufferEnd;
|
||||
// we're on the last line
|
||||
_end = documentEnd;
|
||||
bufferSize.IncrementInBounds(_end, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
// expand to line
|
||||
_start.X = 0;
|
||||
_end.X = 0;
|
||||
_end.Y = base::ClampAdd(_start.Y, 1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO GH#6986: properly handle "end of buffer" as last character
|
||||
// instead of last cell
|
||||
// expand to document
|
||||
_start = bufferSize.Origin();
|
||||
_end = bufferSize.EndExclusive();
|
||||
_end = documentEnd;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -608,7 +606,7 @@ try
|
|||
*ppRetVal = nullptr;
|
||||
|
||||
const std::wstring queryText{ text, SysStringLen(text) };
|
||||
const auto bufferSize = _getBufferSize();
|
||||
const auto bufferSize = _getOptimizedBufferSize();
|
||||
const auto sensitivity = ignoreCase ? Search::Sensitivity::CaseInsensitive : Search::Sensitivity::CaseSensitive;
|
||||
|
||||
auto searchDirection = Search::Direction::Forward;
|
||||
|
@ -1016,11 +1014,24 @@ try
|
|||
_pData->UnlockConsole();
|
||||
});
|
||||
|
||||
// We can abstract this movement by moving _start
|
||||
// GH#7342: check if we're past the documentEnd
|
||||
// If so, clamp each endpoint to the end of the document.
|
||||
constexpr auto endpoint = TextPatternRangeEndpoint::TextPatternRangeEndpoint_Start;
|
||||
const auto bufferSize{ _pData->GetTextBuffer().GetSize() };
|
||||
const COORD documentEnd = _getDocumentEnd();
|
||||
if (bufferSize.CompareInBounds(_start, documentEnd, true) > 0)
|
||||
{
|
||||
_start = documentEnd;
|
||||
}
|
||||
if (bufferSize.CompareInBounds(_end, documentEnd, true) > 0)
|
||||
{
|
||||
_end = documentEnd;
|
||||
}
|
||||
|
||||
const auto wasDegenerate = IsDegenerate();
|
||||
if (count != 0)
|
||||
{
|
||||
// We can abstract this movement by moving _start
|
||||
constexpr auto endpoint = TextPatternRangeEndpoint::TextPatternRangeEndpoint_Start;
|
||||
const auto preventBoundary = !wasDegenerate;
|
||||
if (unit == TextUnit::TextUnit_Character)
|
||||
{
|
||||
|
@ -1028,13 +1039,7 @@ try
|
|||
}
|
||||
else if (unit <= TextUnit::TextUnit_Word)
|
||||
{
|
||||
// TODO GH#10925: passing in "true" instead of "preventBoundary"
|
||||
// We still need to go through the process of writing
|
||||
// tests, finding failing cases, and fixing them.
|
||||
// For now, just use true because we've been doing that so far.
|
||||
// The tests at the time of writing don't report any failures
|
||||
// if we use one over the other.
|
||||
_moveEndpointByUnitWord(count, endpoint, pRetVal, true);
|
||||
_moveEndpointByUnitWord(count, endpoint, pRetVal, preventBoundary);
|
||||
}
|
||||
else if (unit <= TextUnit::TextUnit_Line)
|
||||
{
|
||||
|
@ -1080,6 +1085,26 @@ IFACEMETHODIMP UiaTextRangeBase::MoveEndpointByUnit(_In_ TextPatternRangeEndpoin
|
|||
_pData->UnlockConsole();
|
||||
});
|
||||
|
||||
// GH#7342: check if we're past the documentEnd
|
||||
// If so, clamp each endpoint to the end of the document.
|
||||
const auto bufferSize{ _pData->GetTextBuffer().GetSize() };
|
||||
|
||||
auto documentEnd = bufferSize.EndExclusive();
|
||||
try
|
||||
{
|
||||
documentEnd = _getDocumentEnd();
|
||||
}
|
||||
CATCH_LOG();
|
||||
|
||||
if (bufferSize.CompareInBounds(_start, documentEnd, true) > 0)
|
||||
{
|
||||
_start = documentEnd;
|
||||
}
|
||||
if (bufferSize.CompareInBounds(_end, documentEnd, true) > 0)
|
||||
{
|
||||
_end = documentEnd;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (unit == TextUnit::TextUnit_Character)
|
||||
|
@ -1307,7 +1332,7 @@ const unsigned int UiaTextRangeBase::_getViewportHeight(const SMALL_RECT viewpor
|
|||
// - <none>
|
||||
// Return Value:
|
||||
// - A viewport representing the portion of the TextBuffer that has valid text
|
||||
const Viewport UiaTextRangeBase::_getBufferSize() const noexcept
|
||||
const Viewport UiaTextRangeBase::_getOptimizedBufferSize() const noexcept
|
||||
{
|
||||
// we need to add 1 to the X/Y of textBufferEnd
|
||||
// because we want the returned viewport to include this COORD
|
||||
|
@ -1318,6 +1343,20 @@ const Viewport UiaTextRangeBase::_getBufferSize() const noexcept
|
|||
return Viewport::FromDimensions({ 0, 0 }, width, height);
|
||||
}
|
||||
|
||||
// We consider the "document end" to be the line beneath the cursor or
|
||||
// last legible character (whichever is further down). In the event where
|
||||
// the last legible character is on the last line of the buffer,
|
||||
// we use the "end exclusive" position (left-most point on a line one past the end of the buffer).
|
||||
// NOTE: "end exclusive" is naturally computed using the heuristic above.
|
||||
const til::point UiaTextRangeBase::_getDocumentEnd() const
|
||||
{
|
||||
const auto optimizedBufferSize{ _getOptimizedBufferSize() };
|
||||
const auto& buffer{ _pData->GetTextBuffer() };
|
||||
const auto lastCharPos{ buffer.GetLastNonSpaceCharacter(optimizedBufferSize) };
|
||||
const auto cursorPos{ buffer.GetCursor().GetPosition() };
|
||||
return { optimizedBufferSize.Left(), std::max(lastCharPos.Y, cursorPos.Y) + 1 };
|
||||
}
|
||||
|
||||
// Routine Description:
|
||||
// - adds the relevant coordinate points from the row to coords.
|
||||
// - it is assumed that startAnchor and endAnchor are within the same row
|
||||
|
@ -1388,19 +1427,20 @@ void UiaTextRangeBase::_moveEndpointByUnitCharacter(_In_ const int moveCount,
|
|||
|
||||
bool success = true;
|
||||
til::point target = GetEndpoint(endpoint);
|
||||
const auto documentEnd{ _getDocumentEnd() };
|
||||
while (std::abs(*pAmountMoved) < std::abs(moveCount) && success)
|
||||
{
|
||||
switch (moveDirection)
|
||||
{
|
||||
case MovementDirection::Forward:
|
||||
success = buffer.MoveToNextGlyph(target, allowBottomExclusive);
|
||||
success = buffer.MoveToNextGlyph(target, allowBottomExclusive, documentEnd);
|
||||
if (success)
|
||||
{
|
||||
(*pAmountMoved)++;
|
||||
}
|
||||
break;
|
||||
case MovementDirection::Backward:
|
||||
success = buffer.MoveToPreviousGlyph(target);
|
||||
success = buffer.MoveToPreviousGlyph(target, documentEnd);
|
||||
if (success)
|
||||
{
|
||||
(*pAmountMoved)--;
|
||||
|
@ -1441,10 +1481,9 @@ void UiaTextRangeBase::_moveEndpointByUnitWord(_In_ const int moveCount,
|
|||
const bool allowBottomExclusive = !preventBufferEnd;
|
||||
const MovementDirection moveDirection = (moveCount > 0) ? MovementDirection::Forward : MovementDirection::Backward;
|
||||
const auto& buffer = _pData->GetTextBuffer();
|
||||
const auto bufferSize = _getBufferSize();
|
||||
const auto bufferSize = buffer.GetSize();
|
||||
const auto bufferOrigin = bufferSize.Origin();
|
||||
const auto bufferEnd = bufferSize.EndExclusive();
|
||||
const auto lastCharPos = buffer.GetLastNonSpaceCharacter(bufferSize);
|
||||
const auto documentEnd = _getDocumentEnd();
|
||||
|
||||
auto resultPos = GetEndpoint(endpoint);
|
||||
auto nextPos = resultPos;
|
||||
|
@ -1457,18 +1496,18 @@ void UiaTextRangeBase::_moveEndpointByUnitWord(_In_ const int moveCount,
|
|||
{
|
||||
case MovementDirection::Forward:
|
||||
{
|
||||
if (nextPos == bufferEnd)
|
||||
if (bufferSize.CompareInBounds(nextPos, documentEnd, true) >= 0)
|
||||
{
|
||||
success = false;
|
||||
}
|
||||
else if (buffer.MoveToNextWord(nextPos, _wordDelimiters, lastCharPos))
|
||||
else if (buffer.MoveToNextWord(nextPos, _wordDelimiters, documentEnd))
|
||||
{
|
||||
resultPos = nextPos;
|
||||
(*pAmountMoved)++;
|
||||
}
|
||||
else if (allowBottomExclusive)
|
||||
{
|
||||
resultPos = bufferEnd;
|
||||
resultPos = documentEnd;
|
||||
(*pAmountMoved)++;
|
||||
}
|
||||
else
|
||||
|
@ -1529,10 +1568,18 @@ void UiaTextRangeBase::_moveEndpointByUnitLine(_In_ const int moveCount,
|
|||
|
||||
const bool allowBottomExclusive = !preventBoundary;
|
||||
const MovementDirection moveDirection = (moveCount > 0) ? MovementDirection::Forward : MovementDirection::Backward;
|
||||
const auto bufferSize = _getBufferSize();
|
||||
const auto bufferSize = _getOptimizedBufferSize();
|
||||
|
||||
auto documentEnd{ bufferSize.EndExclusive() };
|
||||
try
|
||||
{
|
||||
documentEnd = _getDocumentEnd();
|
||||
}
|
||||
CATCH_LOG();
|
||||
|
||||
bool success = true;
|
||||
auto resultPos = GetEndpoint(endpoint);
|
||||
|
||||
while (std::abs(*pAmountMoved) < std::abs(moveCount) && success)
|
||||
{
|
||||
auto nextPos = resultPos;
|
||||
|
@ -1540,22 +1587,29 @@ void UiaTextRangeBase::_moveEndpointByUnitLine(_In_ const int moveCount,
|
|||
{
|
||||
case MovementDirection::Forward:
|
||||
{
|
||||
// can't move past end
|
||||
if (nextPos.Y >= bufferSize.BottomInclusive())
|
||||
if (nextPos.Y >= documentEnd.Y)
|
||||
{
|
||||
if (preventBoundary || nextPos == bufferSize.EndExclusive())
|
||||
{
|
||||
success = false;
|
||||
break;
|
||||
}
|
||||
// Corner Case: we're past the limit
|
||||
// Clamp us to the limit
|
||||
resultPos = documentEnd;
|
||||
success = false;
|
||||
}
|
||||
|
||||
nextPos.X = bufferSize.RightInclusive();
|
||||
success = bufferSize.IncrementInBounds(nextPos, allowBottomExclusive);
|
||||
if (success)
|
||||
else if (preventBoundary && nextPos.Y == base::ClampSub(documentEnd.Y, 1))
|
||||
{
|
||||
resultPos = nextPos;
|
||||
(*pAmountMoved)++;
|
||||
// Corner Case: we're just before the limit
|
||||
// and we're not allowed onto the exclusive end.
|
||||
// Fail to move.
|
||||
success = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
nextPos.X = bufferSize.RightInclusive();
|
||||
success = bufferSize.IncrementInBounds(nextPos, allowBottomExclusive);
|
||||
if (success)
|
||||
{
|
||||
resultPos = nextPos;
|
||||
(*pAmountMoved)++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -1621,15 +1675,21 @@ void UiaTextRangeBase::_moveEndpointByUnitDocument(_In_ const int moveCount,
|
|||
}
|
||||
|
||||
const MovementDirection moveDirection = (moveCount > 0) ? MovementDirection::Forward : MovementDirection::Backward;
|
||||
const auto bufferSize = _getBufferSize();
|
||||
const auto bufferSize = _getOptimizedBufferSize();
|
||||
|
||||
const auto target = GetEndpoint(endpoint);
|
||||
switch (moveDirection)
|
||||
{
|
||||
case MovementDirection::Forward:
|
||||
{
|
||||
const auto documentEnd = bufferSize.EndExclusive();
|
||||
if (preventBoundary || target == documentEnd)
|
||||
auto documentEnd{ bufferSize.EndExclusive() };
|
||||
try
|
||||
{
|
||||
documentEnd = _getDocumentEnd();
|
||||
}
|
||||
CATCH_LOG();
|
||||
|
||||
if (preventBoundary || bufferSize.CompareInBounds(target, documentEnd, true) >= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -149,7 +149,8 @@ namespace Microsoft::Console::Types
|
|||
virtual const COORD _getScreenFontSize() const;
|
||||
|
||||
const unsigned int _getViewportHeight(const SMALL_RECT viewport) const noexcept;
|
||||
const Viewport _getBufferSize() const noexcept;
|
||||
const Viewport _getOptimizedBufferSize() const noexcept;
|
||||
const til::point _getDocumentEnd() const;
|
||||
|
||||
void _getBoundingRect(const til::rectangle textRect, _Inout_ std::vector<double>& coords) const;
|
||||
|
||||
|
|
|
@ -21,7 +21,6 @@ $result = "// Copyright (c) Microsoft Corporation.
|
|||
// These were generated by tools\TestTableWriter\GenerateTests.ps1
|
||||
// Read tools\TestTableWriter\README.md for more details"
|
||||
|
||||
# TODO: THIS IS PROBABLY WRONG. Bottom/Right are exclusive (I think?)
|
||||
# 1. Define a few helpful variables to make life easier.
|
||||
$result += "
|
||||
// Define a few helpful variables
|
||||
|
@ -29,11 +28,16 @@ constexpr til::rectangle bufferSize{ 0, 0, 80, 300 };
|
|||
constexpr short midX{ 40 };
|
||||
constexpr short midY{ 150 };
|
||||
constexpr short midPopulatedY{ 75 };
|
||||
constexpr short segment0{ 0 };
|
||||
constexpr short segment1{ 16 };
|
||||
constexpr short segment2{ 32 };
|
||||
constexpr short segment3{ 48 };
|
||||
constexpr short segment4{ 64 };
|
||||
constexpr til::point origin{ 0, 0 };
|
||||
constexpr til::point midTop{ midX, 0 };
|
||||
constexpr til::point midHistory{ midX, midPopulatedY };
|
||||
constexpr til::point midDocEnd{ midX, midY };
|
||||
constexpr til::point lastCharPos{ 79, midY };
|
||||
constexpr til::point lastCharPos{ 72, midY };
|
||||
constexpr til::point docEnd{ 0, midY + 1 };
|
||||
constexpr til::point midEmptySpace{ midX, midY + midPopulatedY };
|
||||
constexpr til::point bufferEnd{ 79, 299 };
|
||||
|
@ -55,17 +59,33 @@ foreach ($test in $tests)
|
|||
$vars.Remove("origin") > $null;
|
||||
$vars.Remove("midTop") > $null;
|
||||
$vars.Remove("midHistory") > $null;
|
||||
$vars.Remove("midDocEnd") > $null;
|
||||
$vars.Remove("lastCharPos") > $null;
|
||||
$vars.Remove("docEnd") > $null;
|
||||
$vars.Remove("midEmptySpace") > $null;
|
||||
$vars.Remove("bufferEnd") > $null;
|
||||
$vars.Remove("endExclusive") > $null;
|
||||
|
||||
# 3.b. Now all of the remaining vars can be deduced from standard vars
|
||||
foreach ($var in $vars)
|
||||
{
|
||||
# Extract the standard var from the name
|
||||
$standardVar = $var.Contains("Left") ? $var.Split("Left") : $var.Substring(0, $var.length - 3);
|
||||
# Figure out what heuristic to use
|
||||
$segmentHeuristic = $var.Contains("segment");
|
||||
$leftHeuristic = $var.Contains("Left");
|
||||
$movementHeuristic = $var -match ".*\d+.*";
|
||||
|
||||
# i. Contains number --> requires movement
|
||||
if ($var -match ".*\d+.*")
|
||||
# i. Contains "segment" --> define point at the beginning of a text segment
|
||||
if ($segmentHeuristic)
|
||||
{
|
||||
$result += "constexpr til::point {0}{{ {1}, {2}.y() }};" -f $var, $var.Substring(0, 8), $var.Substring(9, $var.Length - $var.IndexOf("L") - 1);
|
||||
}
|
||||
# ii. Contains number --> requires movement
|
||||
elseif ($movementHeuristic)
|
||||
{
|
||||
# everything excluding last 3 characters denotes the standard variable
|
||||
# we're based on.
|
||||
$standardVar = $var.Substring(0, $var.length - 3);
|
||||
|
||||
# 3rd to last character denotes the movement direction
|
||||
# P --> plus/forwards
|
||||
# M --> minus/backwards
|
||||
|
@ -101,10 +121,11 @@ foreach ($var in $vars)
|
|||
Default { Write-Host "Error: unknown variable movement type" -ForegroundColor Red }
|
||||
}
|
||||
}
|
||||
# ii. Contains "Left" --> set X to left
|
||||
elseif ($var.Contains("Left"))
|
||||
# iii. Contains "Left" --> set X to left
|
||||
elseif ($leftHeuristic)
|
||||
{
|
||||
$result += "constexpr til::point " + $var + "{ bufferSize.left(), " + $standardVar + ".y() };";
|
||||
$standardVar = $var.Split("Left")[0]
|
||||
$result += "constexpr til::point {0}{{ bufferSize.left(), {1}.y() }};" -f $var, $standardVar;
|
||||
}
|
||||
$result += "`n";
|
||||
}
|
||||
|
|
|
@ -44,21 +44,21 @@ The Test Table Writer was written as a method to generate UI Automation tests fo
|
|||
- "Command Arguments" --> `$(TargetPath) /name:*uiatextrange*generated* /inproc`
|
||||
|
||||
# Position chart
|
||||
The text buffer is assumed to be partially filled. Specifically, the top half of the text buffer contains text, and each row is filled with 9 segments of alternating text. For visualization,
|
||||
The text buffer is assumed to be partially filled. Specifically, the top half of the text buffer contains text, and each row is filled with 10 segments of alternating text. For visualization,
|
||||
the ascii diagram below shows what the text buffer may look like.
|
||||
```
|
||||
+---------------------------+
|
||||
|1XX XXX X2X XXX XXX|
|
||||
|XXX XXX XXX XXX XXX|
|
||||
|XXX XXX X3X XXX XXX|
|
||||
|XXX XXX XXX XXX XXX|
|
||||
|XXX XXX X4X XXX XX5|
|
||||
|6 |
|
||||
| |
|
||||
| 7 |
|
||||
| |
|
||||
| 8|
|
||||
+---------------------------+
|
||||
+------------------------------+
|
||||
|1XX XXX X2X XXX XXX |
|
||||
|XXX XXX XXX XXX XXX |
|
||||
|XXX XXX X3X XXX XXX |
|
||||
|XXX XXX XXX XXX XXX |
|
||||
|XXX XXX X4X XXX XX5 |
|
||||
|6 |
|
||||
| |
|
||||
| 7 |
|
||||
| |
|
||||
| 8|
|
||||
+------------------------------+
|
||||
9
|
||||
```
|
||||
The following positions are being tested:
|
||||
|
@ -84,6 +84,11 @@ Each position above already has a predefined variable name. However, a few heuri
|
|||
- `C`: move by character. For simplicity, assumes that each character is one-cell wide.
|
||||
- `<name>P<number>L`, `<name>M<number>L`:
|
||||
- same as above, except move by line. For simplicity, assumes that you won't hit a buffer boundary.
|
||||
- `segment#L<name>`
|
||||
- This is mainly used for word navigation to target a segment of text in the buffer.
|
||||
- `segment#` refers to the beginning of a segment of text in a row. The leftmost run of text is `segment0`, whereas the rightmost run of text is `segment4`.
|
||||
- `L<name>` refers to the line number we're targeting, relative to the `<name>` variable. For example, `Lorigin` means that the y-position should be that of `origin`.
|
||||
- Overall, this allows us to target the beginning of segments of text. `segment0Lorigin` and `segment0LmidTop` both refer to the beginning of the first segment of text on the top line (aka `origin`).
|
||||
|
||||
# Helpful terms and concepts
|
||||
- *degenerate*: the text range encompasses no text. Also, means the start and end endpoints are the same.
|
||||
|
|
|
@ -62,195 +62,280 @@ FALSE,3,TextUnit_Line,5,midHistory,midHistoryP1C,5,midHistoryP5L,midHistoryP6L,F
|
|||
TRUE,1,TextUnit_Document,-5,origin,origin,0,origin,origin,FALSE
|
||||
TRUE,1,TextUnit_Document,-1,origin,origin,0,origin,origin,FALSE
|
||||
TRUE,1,TextUnit_Document,0,origin,origin,0,origin,origin,FALSE
|
||||
TRUE,1,TextUnit_Document,1,origin,origin,1,endExclusive,endExclusive,FALSE
|
||||
TRUE,1,TextUnit_Document,5,origin,origin,1,endExclusive,endExclusive,FALSE
|
||||
FALSE,1,TextUnit_Document,-5,origin,originP1C,0,origin,endExclusive,FALSE
|
||||
FALSE,1,TextUnit_Document,-1,origin,originP1C,0,origin,endExclusive,FALSE
|
||||
FALSE,1,TextUnit_Document,0,origin,originP1C,0,origin,endExclusive,FALSE
|
||||
FALSE,1,TextUnit_Document,1,origin,originP1C,0,origin,endExclusive,FALSE
|
||||
FALSE,1,TextUnit_Document,5,origin,originP1C,0,origin,endExclusive,FALSE
|
||||
TRUE,1,TextUnit_Document,1,origin,origin,1,docEnd,docEnd,FALSE
|
||||
TRUE,1,TextUnit_Document,5,origin,origin,1,docEnd,docEnd,FALSE
|
||||
FALSE,1,TextUnit_Document,-5,origin,originP1C,0,origin,docEnd,FALSE
|
||||
FALSE,1,TextUnit_Document,-1,origin,originP1C,0,origin,docEnd,FALSE
|
||||
FALSE,1,TextUnit_Document,0,origin,originP1C,0,origin,docEnd,FALSE
|
||||
FALSE,1,TextUnit_Document,1,origin,originP1C,0,origin,docEnd,FALSE
|
||||
FALSE,1,TextUnit_Document,5,origin,originP1C,0,origin,docEnd,FALSE
|
||||
TRUE,2,TextUnit_Document,-5,midTop,midTop,-1,origin,origin,FALSE
|
||||
TRUE,2,TextUnit_Document,-1,midTop,midTop,-1,origin,origin,FALSE
|
||||
TRUE,2,TextUnit_Document,0,midTop,midTop,0,midTop,midTop,FALSE
|
||||
TRUE,2,TextUnit_Document,1,midTop,midTop,1,endExclusive,endExclusive,FALSE
|
||||
TRUE,2,TextUnit_Document,5,midTop,midTop,1,endExclusive,endExclusive,FALSE
|
||||
FALSE,2,TextUnit_Document,-5,midTop,midTopP1C,0,origin,endExclusive,FALSE
|
||||
FALSE,2,TextUnit_Document,-1,midTop,midTopP1C,0,origin,endExclusive,FALSE
|
||||
FALSE,2,TextUnit_Document,0,midTop,midTopP1C,0,origin,endExclusive,FALSE
|
||||
FALSE,2,TextUnit_Document,1,midTop,midTopP1C,0,origin,endExclusive,FALSE
|
||||
FALSE,2,TextUnit_Document,5,midTop,midTopP1C,0,origin,endExclusive,FALSE
|
||||
TRUE,2,TextUnit_Document,1,midTop,midTop,1,docEnd,docEnd,FALSE
|
||||
TRUE,2,TextUnit_Document,5,midTop,midTop,1,docEnd,docEnd,FALSE
|
||||
FALSE,2,TextUnit_Document,-5,midTop,midTopP1C,0,origin,docEnd,FALSE
|
||||
FALSE,2,TextUnit_Document,-1,midTop,midTopP1C,0,origin,docEnd,FALSE
|
||||
FALSE,2,TextUnit_Document,0,midTop,midTopP1C,0,origin,docEnd,FALSE
|
||||
FALSE,2,TextUnit_Document,1,midTop,midTopP1C,0,origin,docEnd,FALSE
|
||||
FALSE,2,TextUnit_Document,5,midTop,midTopP1C,0,origin,docEnd,FALSE
|
||||
TRUE,3,TextUnit_Document,-5,midHistory,midHistory,-1,origin,origin,FALSE
|
||||
TRUE,3,TextUnit_Document,-1,midHistory,midHistory,-1,origin,origin,FALSE
|
||||
TRUE,3,TextUnit_Document,0,midHistory,midHistory,0,midHistory,midHistory,FALSE
|
||||
TRUE,3,TextUnit_Document,1,midHistory,midHistory,1,endExclusive,endExclusive,FALSE
|
||||
TRUE,3,TextUnit_Document,5,midHistory,midHistory,1,endExclusive,endExclusive,FALSE
|
||||
FALSE,3,TextUnit_Document,-5,midHistory,midHistoryP1C,0,origin,endExclusive,FALSE
|
||||
FALSE,3,TextUnit_Document,-1,midHistory,midHistoryP1C,0,origin,endExclusive,FALSE
|
||||
FALSE,3,TextUnit_Document,0,midHistory,midHistoryP1C,0,origin,endExclusive,FALSE
|
||||
FALSE,3,TextUnit_Document,1,midHistory,midHistoryP1C,0,origin,endExclusive,FALSE
|
||||
FALSE,3,TextUnit_Document,5,midHistory,midHistoryP1C,0,origin,endExclusive,FALSE
|
||||
TRUE,8,TextUnit_Character,-5,bufferEnd,bufferEnd,-5,bufferEndM5C,bufferEndM5C,FALSE
|
||||
TRUE,8,TextUnit_Character,-1,bufferEnd,bufferEnd,-1,bufferEndM1C,bufferEndM1C,FALSE
|
||||
TRUE,8,TextUnit_Character,0,bufferEnd,bufferEnd,0,bufferEnd,bufferEnd,FALSE
|
||||
TRUE,8,TextUnit_Character,1,bufferEnd,bufferEnd,1,endExclusive,endExclusive,TRUE
|
||||
TRUE,8,TextUnit_Character,5,bufferEnd,bufferEnd,1,endExclusive,endExclusive,TRUE
|
||||
FALSE,8,TextUnit_Character,-5,bufferEnd,endExclusive,-5,bufferEndM5C,bufferEndM4C,FALSE
|
||||
FALSE,8,TextUnit_Character,-1,bufferEnd,endExclusive,-1,bufferEndM1C,bufferEnd,FALSE
|
||||
FALSE,8,TextUnit_Character,0,bufferEnd,endExclusive,0,bufferEnd,endExclusive,FALSE
|
||||
FALSE,8,TextUnit_Character,1,bufferEnd,endExclusive,0,bufferEnd,endExclusive,FALSE
|
||||
FALSE,8,TextUnit_Character,5,bufferEnd,endExclusive,0,bufferEnd,endExclusive,FALSE
|
||||
TRUE,8,TextUnit_Line,-5,bufferEnd,bufferEnd,-5,bufferEndM4L,bufferEndM4L,FALSE
|
||||
TRUE,8,TextUnit_Line,-1,bufferEnd,bufferEnd,-1,bufferEndLeft,bufferEndLeft,FALSE
|
||||
TRUE,8,TextUnit_Line,0,bufferEnd,bufferEnd,0,bufferEnd,bufferEnd,FALSE
|
||||
TRUE,8,TextUnit_Line,1,bufferEnd,bufferEnd,1,endExclusive,endExclusive,TRUE
|
||||
TRUE,8,TextUnit_Line,5,bufferEnd,bufferEnd,1,endExclusive,endExclusive,TRUE
|
||||
FALSE,8,TextUnit_Line,-5,bufferEnd,endExclusive,-5,bufferEndM5L,bufferEndM4L,TRUE
|
||||
FALSE,8,TextUnit_Line,-1,bufferEnd,endExclusive,-1,bufferEndM1L,bufferEndLeft,TRUE
|
||||
FALSE,8,TextUnit_Line,0,bufferEnd,endExclusive,0,bufferEndLeft,endExclusive,TRUE
|
||||
FALSE,8,TextUnit_Line,1,bufferEnd,endExclusive,0,bufferEndLeft,endExclusive,TRUE
|
||||
FALSE,8,TextUnit_Line,5,bufferEnd,endExclusive,0,bufferEndLeft,endExclusive,TRUE
|
||||
TRUE,3,TextUnit_Document,1,midHistory,midHistory,1,docEnd,docEnd,FALSE
|
||||
TRUE,3,TextUnit_Document,5,midHistory,midHistory,1,docEnd,docEnd,FALSE
|
||||
FALSE,3,TextUnit_Document,-5,midHistory,midHistoryP1C,0,origin,docEnd,FALSE
|
||||
FALSE,3,TextUnit_Document,-1,midHistory,midHistoryP1C,0,origin,docEnd,FALSE
|
||||
FALSE,3,TextUnit_Document,0,midHistory,midHistoryP1C,0,origin,docEnd,FALSE
|
||||
FALSE,3,TextUnit_Document,1,midHistory,midHistoryP1C,0,origin,docEnd,FALSE
|
||||
FALSE,3,TextUnit_Document,5,midHistory,midHistoryP1C,0,origin,docEnd,FALSE
|
||||
TRUE,8,TextUnit_Character,-5,bufferEnd,bufferEnd,-5,docEndM5C,docEndM5C,FALSE
|
||||
TRUE,8,TextUnit_Character,-1,bufferEnd,bufferEnd,-1,docEndM1C,docEndM1C,FALSE
|
||||
TRUE,8,TextUnit_Character,0,bufferEnd,bufferEnd,0,docEnd,docEnd,FALSE
|
||||
TRUE,8,TextUnit_Character,1,bufferEnd,bufferEnd,0,docEnd,docEnd,FALSE
|
||||
TRUE,8,TextUnit_Character,5,bufferEnd,bufferEnd,0,docEnd,docEnd,FALSE
|
||||
FALSE,8,TextUnit_Character,-5,bufferEnd,endExclusive,-5,docEndM5C,docEndM5C,FALSE
|
||||
FALSE,8,TextUnit_Character,-1,bufferEnd,endExclusive,-1,docEndM1C,docEndM1C,FALSE
|
||||
FALSE,8,TextUnit_Character,0,bufferEnd,endExclusive,0,docEnd,docEnd,FALSE
|
||||
FALSE,8,TextUnit_Character,1,bufferEnd,endExclusive,0,docEnd,docEnd,FALSE
|
||||
FALSE,8,TextUnit_Character,5,bufferEnd,endExclusive,0,docEnd,docEnd,FALSE
|
||||
TRUE,8,TextUnit_Line,-5,bufferEnd,bufferEnd,-5,docEndM5L,docEndM5L,FALSE
|
||||
TRUE,8,TextUnit_Line,-1,bufferEnd,bufferEnd,-1,docEndM1L,docEndM1L,FALSE
|
||||
TRUE,8,TextUnit_Line,0,bufferEnd,bufferEnd,0,docEnd,docEnd,FALSE
|
||||
TRUE,8,TextUnit_Line,1,bufferEnd,bufferEnd,0,docEnd,docEnd,FALSE
|
||||
TRUE,8,TextUnit_Line,5,bufferEnd,bufferEnd,0,docEnd,docEnd,FALSE
|
||||
FALSE,8,TextUnit_Line,-5,bufferEnd,endExclusive,-5,docEndM5L,docEndM5L,FALSE
|
||||
FALSE,8,TextUnit_Line,-1,bufferEnd,endExclusive,-1,docEndM1L,docEndM1L,FALSE
|
||||
FALSE,8,TextUnit_Line,0,bufferEnd,endExclusive,0,docEnd,docEnd,FALSE
|
||||
FALSE,8,TextUnit_Line,1,bufferEnd,endExclusive,0,docEnd,docEnd,FALSE
|
||||
FALSE,8,TextUnit_Line,5,bufferEnd,endExclusive,0,docEnd,docEnd,FALSE
|
||||
TRUE,8,TextUnit_Document,-5,bufferEnd,bufferEnd,-1,origin,origin,FALSE
|
||||
TRUE,8,TextUnit_Document,-1,bufferEnd,bufferEnd,-1,origin,origin,FALSE
|
||||
TRUE,8,TextUnit_Document,0,bufferEnd,bufferEnd,0,bufferEnd,bufferEnd,FALSE
|
||||
TRUE,8,TextUnit_Document,1,bufferEnd,bufferEnd,1,endExclusive,endExclusive,TRUE
|
||||
TRUE,8,TextUnit_Document,5,bufferEnd,bufferEnd,1,endExclusive,endExclusive,TRUE
|
||||
FALSE,8,TextUnit_Document,-5,bufferEnd,endExclusive,0,origin,endExclusive,TRUE
|
||||
FALSE,8,TextUnit_Document,-1,bufferEnd,endExclusive,0,origin,endExclusive,TRUE
|
||||
FALSE,8,TextUnit_Document,0,bufferEnd,endExclusive,0,origin,endExclusive,TRUE
|
||||
FALSE,8,TextUnit_Document,1,bufferEnd,endExclusive,0,origin,endExclusive,TRUE
|
||||
FALSE,8,TextUnit_Document,5,bufferEnd,endExclusive,0,origin,endExclusive,TRUE
|
||||
TRUE,9,TextUnit_Character,-5,endExclusive,endExclusive,-5,bufferEndM4C,bufferEndM4C,FALSE
|
||||
TRUE,9,TextUnit_Character,-1,endExclusive,endExclusive,-1,bufferEnd,bufferEnd,FALSE
|
||||
TRUE,9,TextUnit_Character,0,endExclusive,endExclusive,0,endExclusive,endExclusive,FALSE
|
||||
TRUE,9,TextUnit_Character,1,endExclusive,endExclusive,0,endExclusive,endExclusive,FALSE
|
||||
TRUE,9,TextUnit_Character,5,endExclusive,endExclusive,0,endExclusive,endExclusive,FALSE
|
||||
TRUE,9,TextUnit_Line,-5,endExclusive,endExclusive,-5,bufferEndM4L,bufferEndM4L,FALSE
|
||||
TRUE,9,TextUnit_Line,-1,endExclusive,endExclusive,-1,bufferEndLeft,bufferEndLeft,FALSE
|
||||
TRUE,9,TextUnit_Line,0,endExclusive,endExclusive,0,endExclusive,endExclusive,FALSE
|
||||
TRUE,9,TextUnit_Line,1,endExclusive,endExclusive,0,endExclusive,endExclusive,FALSE
|
||||
TRUE,9,TextUnit_Line,5,endExclusive,endExclusive,0,endExclusive,endExclusive,FALSE
|
||||
TRUE,8,TextUnit_Document,0,bufferEnd,bufferEnd,0,docEnd,docEnd,FALSE
|
||||
TRUE,8,TextUnit_Document,1,bufferEnd,bufferEnd,0,docEnd,docEnd,FALSE
|
||||
TRUE,8,TextUnit_Document,5,bufferEnd,bufferEnd,0,docEnd,docEnd,FALSE
|
||||
FALSE,8,TextUnit_Document,-5,bufferEnd,endExclusive,-1,origin,origin,FALSE
|
||||
FALSE,8,TextUnit_Document,-1,bufferEnd,endExclusive,-1,origin,origin,FALSE
|
||||
FALSE,8,TextUnit_Document,0,bufferEnd,endExclusive,0,docEnd,docEnd,FALSE
|
||||
FALSE,8,TextUnit_Document,1,bufferEnd,endExclusive,0,docEnd,docEnd,FALSE
|
||||
FALSE,8,TextUnit_Document,5,bufferEnd,endExclusive,0,docEnd,docEnd,FALSE
|
||||
TRUE,9,TextUnit_Character,-5,endExclusive,endExclusive,-5,docEndM5C,docEndM5C,FALSE
|
||||
TRUE,9,TextUnit_Character,-1,endExclusive,endExclusive,-1,docEndM1C,docEndM1C,FALSE
|
||||
TRUE,9,TextUnit_Character,0,endExclusive,endExclusive,0,docEnd,docEnd,FALSE
|
||||
TRUE,9,TextUnit_Character,1,endExclusive,endExclusive,0,docEnd,docEnd,FALSE
|
||||
TRUE,9,TextUnit_Character,5,endExclusive,endExclusive,0,docEnd,docEnd,FALSE
|
||||
TRUE,9,TextUnit_Line,-5,endExclusive,endExclusive,-5,docEndM5L,docEndM5L,FALSE
|
||||
TRUE,9,TextUnit_Line,-1,endExclusive,endExclusive,-1,docEndM1L,docEndM1L,FALSE
|
||||
TRUE,9,TextUnit_Line,0,endExclusive,endExclusive,0,docEnd,docEnd,FALSE
|
||||
TRUE,9,TextUnit_Line,1,endExclusive,endExclusive,0,docEnd,docEnd,FALSE
|
||||
TRUE,9,TextUnit_Line,5,endExclusive,endExclusive,0,docEnd,docEnd,FALSE
|
||||
TRUE,9,TextUnit_Document,-5,endExclusive,endExclusive,-1,origin,origin,FALSE
|
||||
TRUE,9,TextUnit_Document,-1,endExclusive,endExclusive,-1,origin,origin,FALSE
|
||||
TRUE,9,TextUnit_Document,0,endExclusive,endExclusive,0,endExclusive,endExclusive,FALSE
|
||||
TRUE,9,TextUnit_Document,1,endExclusive,endExclusive,0,endExclusive,endExclusive,FALSE
|
||||
TRUE,9,TextUnit_Document,5,endExclusive,endExclusive,0,endExclusive,endExclusive,FALSE
|
||||
TRUE,4,TextUnit_Character,-5,midDocEnd,midDocEnd,-5,midDocEndM5C,midDocEndM5C,TRUE
|
||||
TRUE,4,TextUnit_Character,-1,midDocEnd,midDocEnd,-1,midDocEndM1C,midDocEndM1C,TRUE
|
||||
TRUE,4,TextUnit_Character,0,midDocEnd,midDocEnd,0,midDocEnd,midDocEnd,TRUE
|
||||
TRUE,4,TextUnit_Character,1,midDocEnd,midDocEnd,1,midDocEndP1C,midDocEndP1C,TRUE
|
||||
TRUE,4,TextUnit_Character,5,midDocEnd,midDocEnd,5,midDocEndP5C,midDocEndP5C,TRUE
|
||||
FALSE,4,TextUnit_Character,-5,midDocEnd,midDocEndP1C,-5,midDocEndM5C,midDocEndM4C,TRUE
|
||||
FALSE,4,TextUnit_Character,-1,midDocEnd,midDocEndP1C,-1,midDocEndM1C,midDocEnd,TRUE
|
||||
FALSE,4,TextUnit_Character,0,midDocEnd,midDocEndP1C,0,midDocEnd,midDocEndP1C,TRUE
|
||||
FALSE,4,TextUnit_Character,1,midDocEnd,midDocEndP1C,1,midDocEndP1C,midDocEndP2C,TRUE
|
||||
FALSE,4,TextUnit_Character,5,midDocEnd,midDocEndP1C,5,midDocEndP5C,midDocEndP6C,TRUE
|
||||
TRUE,4,TextUnit_Line,-5,midDocEnd,midDocEnd,-5,midDocEndM4L,midDocEndM4L,TRUE
|
||||
TRUE,4,TextUnit_Line,-1,midDocEnd,midDocEnd,-1,midDocEndLeft,midDocEndLeft,TRUE
|
||||
TRUE,4,TextUnit_Line,0,midDocEnd,midDocEnd,0,midDocEnd,midDocEnd,TRUE
|
||||
TRUE,4,TextUnit_Line,1,midDocEnd,midDocEnd,1,docEnd,docEnd,TRUE
|
||||
TRUE,4,TextUnit_Line,5,midDocEnd,midDocEnd,1,docEnd,docEnd,TRUE
|
||||
FALSE,4,TextUnit_Line,-5,midDocEnd,midDocEndP1C,-5,midDocEndM5L,midDocEndM4L,TRUE
|
||||
FALSE,4,TextUnit_Line,-1,midDocEnd,midDocEndP1C,-1,midDocEndM1L,midDocEndLeft,TRUE
|
||||
FALSE,4,TextUnit_Line,0,midDocEnd,midDocEndP1C,0,midDocEndLeft,docEnd,TRUE
|
||||
FALSE,4,TextUnit_Line,1,midDocEnd,midDocEndP1C,0,midDocEndLeft,docEnd,TRUE
|
||||
FALSE,4,TextUnit_Line,5,midDocEnd,midDocEndP1C,0,midDocEndLeft,docEnd,TRUE
|
||||
TRUE,4,TextUnit_Document,-5,midDocEnd,midDocEnd,-1,origin,origin,TRUE
|
||||
TRUE,4,TextUnit_Document,-1,midDocEnd,midDocEnd,-1,origin,origin,TRUE
|
||||
TRUE,4,TextUnit_Document,0,midDocEnd,midDocEnd,0,midDocEnd,midDocEnd,TRUE
|
||||
TRUE,4,TextUnit_Document,1,midDocEnd,midDocEnd,1,docEnd,docEnd,TRUE
|
||||
TRUE,4,TextUnit_Document,5,midDocEnd,midDocEnd,1,docEnd,docEnd,TRUE
|
||||
FALSE,4,TextUnit_Document,-5,midDocEnd,midDocEndP1C,0,origin,docEnd,TRUE
|
||||
FALSE,4,TextUnit_Document,-1,midDocEnd,midDocEndP1C,0,origin,docEnd,TRUE
|
||||
FALSE,4,TextUnit_Document,0,midDocEnd,midDocEndP1C,0,origin,docEnd,TRUE
|
||||
FALSE,4,TextUnit_Document,1,midDocEnd,midDocEndP1C,0,origin,docEnd,TRUE
|
||||
FALSE,4,TextUnit_Document,5,midDocEnd,midDocEndP1C,0,origin,docEnd,TRUE
|
||||
TRUE,5,TextUnit_Character,-5,lastCharPos,lastCharPos,-5,lastCharPosM5C,lastCharPosM5C,TRUE
|
||||
TRUE,5,TextUnit_Character,-1,lastCharPos,lastCharPos,-1,lastCharPosM1C,lastCharPosM1C,TRUE
|
||||
TRUE,5,TextUnit_Character,0,lastCharPos,lastCharPos,0,lastCharPos,lastCharPos,TRUE
|
||||
TRUE,5,TextUnit_Character,1,lastCharPos,lastCharPos,1,docEnd,docEnd,TRUE
|
||||
TRUE,5,TextUnit_Character,5,lastCharPos,lastCharPos,1,docEnd,docEnd,TRUE
|
||||
FALSE,5,TextUnit_Character,-5,lastCharPos,lastCharPosP1C,-5,lastCharPosM5C,lastCharPosM4C,TRUE
|
||||
FALSE,5,TextUnit_Character,-1,lastCharPos,lastCharPosP1C,-1,lastCharPosM1C,lastCharPos,TRUE
|
||||
FALSE,5,TextUnit_Character,0,lastCharPos,lastCharPosP1C,0,lastCharPos,docEnd,TRUE
|
||||
FALSE,5,TextUnit_Character,1,lastCharPos,lastCharPosP1C,0,lastCharPos,docEnd,TRUE
|
||||
FALSE,5,TextUnit_Character,5,lastCharPos,lastCharPosP1C,0,lastCharPos,docEnd,TRUE
|
||||
TRUE,5,TextUnit_Line,-5,lastCharPos,lastCharPos,-5,lastCharPosM4L,lastCharPosM4L,TRUE
|
||||
TRUE,5,TextUnit_Line,-1,lastCharPos,lastCharPos,-1,lastCharPosLeft,lastCharPosLeft,TRUE
|
||||
TRUE,5,TextUnit_Line,0,lastCharPos,lastCharPos,0,lastCharPos,lastCharPos,TRUE
|
||||
TRUE,5,TextUnit_Line,1,lastCharPos,lastCharPos,1,docEnd,docEnd,TRUE
|
||||
TRUE,5,TextUnit_Line,5,lastCharPos,lastCharPos,1,docEnd,docEnd,TRUE
|
||||
FALSE,5,TextUnit_Line,-5,lastCharPos,lastCharPosP1C,-5,lastCharPosM5L,lastCharPosM4L,TRUE
|
||||
FALSE,5,TextUnit_Line,-1,lastCharPos,lastCharPosP1C,-1,lastCharPosM1L,lastCharPosLeft,TRUE
|
||||
FALSE,5,TextUnit_Line,0,lastCharPos,lastCharPosP1C,0,lastCharPosLeft,docEnd,TRUE
|
||||
FALSE,5,TextUnit_Line,1,lastCharPos,lastCharPosP1C,0,lastCharPosLeft,docEnd,TRUE
|
||||
FALSE,5,TextUnit_Line,5,lastCharPos,lastCharPosP1C,0,lastCharPosLeft,docEnd,TRUE
|
||||
TRUE,5,TextUnit_Document,-5,lastCharPos,lastCharPos,-1,origin,origin,TRUE
|
||||
TRUE,5,TextUnit_Document,-1,lastCharPos,lastCharPos,-1,origin,origin,TRUE
|
||||
TRUE,5,TextUnit_Document,0,lastCharPos,lastCharPos,0,lastCharPos,lastCharPos,TRUE
|
||||
TRUE,5,TextUnit_Document,1,lastCharPos,lastCharPos,1,docEnd,docEnd,TRUE
|
||||
TRUE,5,TextUnit_Document,5,lastCharPos,lastCharPos,1,docEnd,docEnd,TRUE
|
||||
FALSE,5,TextUnit_Document,-5,lastCharPos,lastCharPosP1C,0,origin,docEnd,TRUE
|
||||
FALSE,5,TextUnit_Document,-1,lastCharPos,lastCharPosP1C,0,origin,docEnd,TRUE
|
||||
FALSE,5,TextUnit_Document,0,lastCharPos,lastCharPosP1C,0,origin,docEnd,TRUE
|
||||
FALSE,5,TextUnit_Document,1,lastCharPos,lastCharPosP1C,0,origin,docEnd,TRUE
|
||||
FALSE,5,TextUnit_Document,5,lastCharPos,lastCharPosP1C,0,origin,docEnd,TRUE
|
||||
TRUE,6,TextUnit_Character,-5,docEnd,docEnd,-5,docEndM5C,docEndM5C,TRUE
|
||||
TRUE,6,TextUnit_Character,-1,docEnd,docEnd,-1,docEndM1C,docEndM1C,TRUE
|
||||
TRUE,6,TextUnit_Character,0,docEnd,docEnd,0,docEnd,docEnd,TRUE
|
||||
TRUE,6,TextUnit_Character,1,docEnd,docEnd,0,docEnd,docEnd,TRUE
|
||||
TRUE,6,TextUnit_Character,5,docEnd,docEnd,0,docEnd,docEnd,TRUE
|
||||
FALSE,6,TextUnit_Character,-5,docEnd,docEndP1C,-5,docEndM5C,docEndM5C,TRUE
|
||||
FALSE,6,TextUnit_Character,-1,docEnd,docEndP1C,-1,docEndM1C,docEndM1C,TRUE
|
||||
FALSE,6,TextUnit_Character,0,docEnd,docEndP1C,0,docEnd,docEnd,TRUE
|
||||
FALSE,6,TextUnit_Character,1,docEnd,docEndP1C,0,docEnd,docEnd,TRUE
|
||||
FALSE,6,TextUnit_Character,5,docEnd,docEndP1C,0,docEnd,docEnd,TRUE
|
||||
TRUE,6,TextUnit_Line,-5,docEnd,docEnd,-5,docEndM4L,docEndM4L,TRUE
|
||||
TRUE,6,TextUnit_Line,-1,docEnd,docEnd,-1,docEndLeft,docEndLeft,TRUE
|
||||
TRUE,6,TextUnit_Line,0,docEnd,docEnd,0,docEnd,docEnd,TRUE
|
||||
TRUE,6,TextUnit_Line,1,docEnd,docEnd,0,docEnd,docEnd,TRUE
|
||||
TRUE,6,TextUnit_Line,5,docEnd,docEnd,0,docEnd,docEnd,TRUE
|
||||
FALSE,6,TextUnit_Line,-5,docEnd,docEndP1C,-5,docEndM4L,docEndM4L,TRUE
|
||||
FALSE,6,TextUnit_Line,-1,docEnd,docEndP1C,-1,docEndLeft,docEndLeft,TRUE
|
||||
FALSE,6,TextUnit_Line,0,docEnd,docEndP1C,0,docEnd,docEnd,TRUE
|
||||
FALSE,6,TextUnit_Line,1,docEnd,docEndP1C,0,docEnd,docEnd,TRUE
|
||||
FALSE,6,TextUnit_Line,5,docEnd,docEndP1C,0,docEnd,docEnd,TRUE
|
||||
TRUE,6,TextUnit_Document,-5,docEnd,docEnd,-1,origin,origin,TRUE
|
||||
TRUE,6,TextUnit_Document,-1,docEnd,docEnd,-1,origin,origin,TRUE
|
||||
TRUE,6,TextUnit_Document,0,docEnd,docEnd,0,docEnd,docEnd,TRUE
|
||||
TRUE,6,TextUnit_Document,1,docEnd,docEnd,0,docEnd,docEnd,TRUE
|
||||
TRUE,6,TextUnit_Document,5,docEnd,docEnd,0,docEnd,docEnd,TRUE
|
||||
FALSE,6,TextUnit_Document,-5,docEnd,docEndP1C,-1,origin,origin,TRUE
|
||||
FALSE,6,TextUnit_Document,-1,docEnd,docEndP1C,-1,origin,origin,TRUE
|
||||
FALSE,6,TextUnit_Document,0,docEnd,docEndP1C,0,docEnd,docEnd,TRUE
|
||||
FALSE,6,TextUnit_Document,1,docEnd,docEndP1C,0,docEnd,docEnd,TRUE
|
||||
FALSE,6,TextUnit_Document,5,docEnd,docEndP1C,0,docEnd,docEnd,TRUE
|
||||
TRUE,7,TextUnit_Character,-5,midEmptySpace,midEmptySpace,-5,docEndM5C,docEndM5C,TRUE
|
||||
TRUE,7,TextUnit_Character,-1,midEmptySpace,midEmptySpace,-1,docEndM1C,docEndM1C,TRUE
|
||||
TRUE,7,TextUnit_Character,0,midEmptySpace,midEmptySpace,0,docEnd,docEnd,TRUE
|
||||
TRUE,7,TextUnit_Character,1,midEmptySpace,midEmptySpace,0,docEnd,docEnd,TRUE
|
||||
TRUE,7,TextUnit_Character,5,midEmptySpace,midEmptySpace,0,docEnd,docEnd,TRUE
|
||||
FALSE,7,TextUnit_Character,-5,midEmptySpace,midEmptySpaceP1C,-5,docEndM5C,docEndM5C,TRUE
|
||||
FALSE,7,TextUnit_Character,-1,midEmptySpace,midEmptySpaceP1C,-1,docEndM1C,docEndM1C,TRUE
|
||||
FALSE,7,TextUnit_Character,0,midEmptySpace,midEmptySpaceP1C,0,docEnd,docEnd,TRUE
|
||||
FALSE,7,TextUnit_Character,1,midEmptySpace,midEmptySpaceP1C,0,docEnd,docEnd,TRUE
|
||||
FALSE,7,TextUnit_Character,5,midEmptySpace,midEmptySpaceP1C,0,docEnd,docEnd,TRUE
|
||||
TRUE,7,TextUnit_Line,-5,midEmptySpace,midEmptySpace,-5,docEndM4L,docEndM4L,TRUE
|
||||
TRUE,7,TextUnit_Line,-1,midEmptySpace,midEmptySpace,-1,docEndLeft,docEndLeft,TRUE
|
||||
TRUE,7,TextUnit_Line,0,midEmptySpace,midEmptySpace,0,docEnd,docEnd,TRUE
|
||||
TRUE,7,TextUnit_Line,1,midEmptySpace,midEmptySpace,0,docEnd,docEnd,TRUE
|
||||
TRUE,7,TextUnit_Line,5,midEmptySpace,midEmptySpace,0,docEnd,docEnd,TRUE
|
||||
FALSE,7,TextUnit_Line,-5,midEmptySpace,midEmptySpaceP1C,-5,docEndM4L,docEndM4L,TRUE
|
||||
FALSE,7,TextUnit_Line,-1,midEmptySpace,midEmptySpaceP1C,-1,docEndLeft,docEndLeft,TRUE
|
||||
FALSE,7,TextUnit_Line,0,midEmptySpace,midEmptySpaceP1C,0,docEnd,docEnd,TRUE
|
||||
FALSE,7,TextUnit_Line,1,midEmptySpace,midEmptySpaceP1C,0,docEnd,docEnd,TRUE
|
||||
FALSE,7,TextUnit_Line,5,midEmptySpace,midEmptySpaceP1C,0,docEnd,docEnd,TRUE
|
||||
TRUE,7,TextUnit_Document,-5,midEmptySpace,midEmptySpace,-1,origin,origin,TRUE
|
||||
TRUE,7,TextUnit_Document,-1,midEmptySpace,midEmptySpace,-1,origin,origin,TRUE
|
||||
TRUE,7,TextUnit_Document,0,midEmptySpace,midEmptySpace,0,docEnd,docEnd,TRUE
|
||||
TRUE,7,TextUnit_Document,1,midEmptySpace,midEmptySpace,0,docEnd,docEnd,TRUE
|
||||
TRUE,7,TextUnit_Document,5,midEmptySpace,midEmptySpace,0,docEnd,docEnd,TRUE
|
||||
FALSE,7,TextUnit_Document,-5,midEmptySpace,midEmptySpaceP1C,-1,origin,origin,TRUE
|
||||
FALSE,7,TextUnit_Document,-1,midEmptySpace,midEmptySpaceP1C,-1,origin,origin,TRUE
|
||||
FALSE,7,TextUnit_Document,0,midEmptySpace,midEmptySpaceP1C,0,docEnd,docEnd,TRUE
|
||||
FALSE,7,TextUnit_Document,1,midEmptySpace,midEmptySpaceP1C,0,docEnd,docEnd,TRUE
|
||||
FALSE,7,TextUnit_Document,5,midEmptySpace,midEmptySpaceP1C,0,docEnd,docEnd,TRUE
|
||||
TRUE,9,TextUnit_Document,0,endExclusive,endExclusive,0,docEnd,docEnd,FALSE
|
||||
TRUE,9,TextUnit_Document,1,endExclusive,endExclusive,0,docEnd,docEnd,FALSE
|
||||
TRUE,9,TextUnit_Document,5,endExclusive,endExclusive,0,docEnd,docEnd,FALSE
|
||||
TRUE,4,TextUnit_Character,-5,midDocEnd,midDocEnd,-5,midDocEndM5C,midDocEndM5C,FALSE
|
||||
TRUE,4,TextUnit_Character,-1,midDocEnd,midDocEnd,-1,midDocEndM1C,midDocEndM1C,FALSE
|
||||
TRUE,4,TextUnit_Character,0,midDocEnd,midDocEnd,0,midDocEnd,midDocEnd,FALSE
|
||||
TRUE,4,TextUnit_Character,1,midDocEnd,midDocEnd,1,midDocEndP1C,midDocEndP1C,FALSE
|
||||
TRUE,4,TextUnit_Character,5,midDocEnd,midDocEnd,5,midDocEndP5C,midDocEndP5C,FALSE
|
||||
FALSE,4,TextUnit_Character,-5,midDocEnd,midDocEndP1C,-5,midDocEndM5C,midDocEndM4C,FALSE
|
||||
FALSE,4,TextUnit_Character,-1,midDocEnd,midDocEndP1C,-1,midDocEndM1C,midDocEnd,FALSE
|
||||
FALSE,4,TextUnit_Character,0,midDocEnd,midDocEndP1C,0,midDocEnd,midDocEndP1C,FALSE
|
||||
FALSE,4,TextUnit_Character,1,midDocEnd,midDocEndP1C,1,midDocEndP1C,midDocEndP2C,FALSE
|
||||
FALSE,4,TextUnit_Character,5,midDocEnd,midDocEndP1C,5,midDocEndP5C,midDocEndP6C,FALSE
|
||||
TRUE,4,TextUnit_Line,-5,midDocEnd,midDocEnd,-5,midDocEndM4L,midDocEndM4L,FALSE
|
||||
TRUE,4,TextUnit_Line,-1,midDocEnd,midDocEnd,-1,midDocEndLeft,midDocEndLeft,FALSE
|
||||
TRUE,4,TextUnit_Line,0,midDocEnd,midDocEnd,0,midDocEnd,midDocEnd,FALSE
|
||||
TRUE,4,TextUnit_Line,1,midDocEnd,midDocEnd,1,docEnd,docEnd,FALSE
|
||||
TRUE,4,TextUnit_Line,5,midDocEnd,midDocEnd,1,docEnd,docEnd,FALSE
|
||||
FALSE,4,TextUnit_Line,-5,midDocEnd,midDocEndP1C,-5,midDocEndM5L,midDocEndM4L,FALSE
|
||||
FALSE,4,TextUnit_Line,-1,midDocEnd,midDocEndP1C,-1,midDocEndM1L,midDocEndLeft,FALSE
|
||||
FALSE,4,TextUnit_Line,0,midDocEnd,midDocEndP1C,0,midDocEndLeft,docEnd,FALSE
|
||||
FALSE,4,TextUnit_Line,1,midDocEnd,midDocEndP1C,0,midDocEndLeft,docEnd,FALSE
|
||||
FALSE,4,TextUnit_Line,5,midDocEnd,midDocEndP1C,0,midDocEndLeft,docEnd,FALSE
|
||||
TRUE,4,TextUnit_Document,-5,midDocEnd,midDocEnd,-1,origin,origin,FALSE
|
||||
TRUE,4,TextUnit_Document,-1,midDocEnd,midDocEnd,-1,origin,origin,FALSE
|
||||
TRUE,4,TextUnit_Document,0,midDocEnd,midDocEnd,0,midDocEnd,midDocEnd,FALSE
|
||||
TRUE,4,TextUnit_Document,1,midDocEnd,midDocEnd,1,docEnd,docEnd,FALSE
|
||||
TRUE,4,TextUnit_Document,5,midDocEnd,midDocEnd,1,docEnd,docEnd,FALSE
|
||||
FALSE,4,TextUnit_Document,-5,midDocEnd,midDocEndP1C,0,origin,docEnd,FALSE
|
||||
FALSE,4,TextUnit_Document,-1,midDocEnd,midDocEndP1C,0,origin,docEnd,FALSE
|
||||
FALSE,4,TextUnit_Document,0,midDocEnd,midDocEndP1C,0,origin,docEnd,FALSE
|
||||
FALSE,4,TextUnit_Document,1,midDocEnd,midDocEndP1C,0,origin,docEnd,FALSE
|
||||
FALSE,4,TextUnit_Document,5,midDocEnd,midDocEndP1C,0,origin,docEnd,FALSE
|
||||
TRUE,5,TextUnit_Character,-5,lastCharPos,lastCharPos,-5,lastCharPosM5C,lastCharPosM5C,FALSE
|
||||
TRUE,5,TextUnit_Character,-1,lastCharPos,lastCharPos,-1,lastCharPosM1C,lastCharPosM1C,FALSE
|
||||
TRUE,5,TextUnit_Character,0,lastCharPos,lastCharPos,0,lastCharPos,lastCharPos,FALSE
|
||||
TRUE,5,TextUnit_Character,1,lastCharPos,lastCharPos,1,lastCharPosP1C,lastCharPosP1C,FALSE
|
||||
TRUE,5,TextUnit_Character,5,lastCharPos,lastCharPos,5,lastCharPosP5C,lastCharPosP5C,FALSE
|
||||
FALSE,5,TextUnit_Character,-5,lastCharPos,lastCharPosP1C,-5,lastCharPosM5C,lastCharPosM4C,FALSE
|
||||
FALSE,5,TextUnit_Character,-1,lastCharPos,lastCharPosP1C,-1,lastCharPosM1C,lastCharPos,FALSE
|
||||
FALSE,5,TextUnit_Character,0,lastCharPos,lastCharPosP1C,0,lastCharPos,lastCharPosP1C,FALSE
|
||||
FALSE,5,TextUnit_Character,1,lastCharPos,lastCharPosP1C,1,lastCharPosP1C,lastCharPosP2C,FALSE
|
||||
FALSE,5,TextUnit_Character,5,lastCharPos,lastCharPosP1C,5,lastCharPosP5C,lastCharPosP6C,FALSE
|
||||
TRUE,5,TextUnit_Line,-5,lastCharPos,lastCharPos,-5,lastCharPosM4L,lastCharPosM4L,FALSE
|
||||
TRUE,5,TextUnit_Line,-1,lastCharPos,lastCharPos,-1,lastCharPosLeft,lastCharPosLeft,FALSE
|
||||
TRUE,5,TextUnit_Line,0,lastCharPos,lastCharPos,0,lastCharPos,lastCharPos,FALSE
|
||||
TRUE,5,TextUnit_Line,1,lastCharPos,lastCharPos,1,docEnd,docEnd,FALSE
|
||||
TRUE,5,TextUnit_Line,5,lastCharPos,lastCharPos,1,docEnd,docEnd,FALSE
|
||||
FALSE,5,TextUnit_Line,-5,lastCharPos,lastCharPosP1C,-5,lastCharPosM5L,lastCharPosM4L,FALSE
|
||||
FALSE,5,TextUnit_Line,-1,lastCharPos,lastCharPosP1C,-1,lastCharPosM1L,lastCharPosLeft,FALSE
|
||||
FALSE,5,TextUnit_Line,0,lastCharPos,lastCharPosP1C,0,lastCharPosLeft,docEnd,FALSE
|
||||
FALSE,5,TextUnit_Line,1,lastCharPos,lastCharPosP1C,0,lastCharPosLeft,docEnd,FALSE
|
||||
FALSE,5,TextUnit_Line,5,lastCharPos,lastCharPosP1C,0,lastCharPosLeft,docEnd,FALSE
|
||||
TRUE,5,TextUnit_Document,-5,lastCharPos,lastCharPos,-1,origin,origin,FALSE
|
||||
TRUE,5,TextUnit_Document,-1,lastCharPos,lastCharPos,-1,origin,origin,FALSE
|
||||
TRUE,5,TextUnit_Document,0,lastCharPos,lastCharPos,0,lastCharPos,lastCharPos,FALSE
|
||||
TRUE,5,TextUnit_Document,1,lastCharPos,lastCharPos,1,docEnd,docEnd,FALSE
|
||||
TRUE,5,TextUnit_Document,5,lastCharPos,lastCharPos,1,docEnd,docEnd,FALSE
|
||||
FALSE,5,TextUnit_Document,-5,lastCharPos,lastCharPosP1C,0,origin,docEnd,FALSE
|
||||
FALSE,5,TextUnit_Document,-1,lastCharPos,lastCharPosP1C,0,origin,docEnd,FALSE
|
||||
FALSE,5,TextUnit_Document,0,lastCharPos,lastCharPosP1C,0,origin,docEnd,FALSE
|
||||
FALSE,5,TextUnit_Document,1,lastCharPos,lastCharPosP1C,0,origin,docEnd,FALSE
|
||||
FALSE,5,TextUnit_Document,5,lastCharPos,lastCharPosP1C,0,origin,docEnd,FALSE
|
||||
TRUE,6,TextUnit_Character,-5,docEnd,docEnd,-5,docEndM5C,docEndM5C,FALSE
|
||||
TRUE,6,TextUnit_Character,-1,docEnd,docEnd,-1,docEndM1C,docEndM1C,FALSE
|
||||
TRUE,6,TextUnit_Character,0,docEnd,docEnd,0,docEnd,docEnd,FALSE
|
||||
TRUE,6,TextUnit_Character,1,docEnd,docEnd,0,docEnd,docEnd,FALSE
|
||||
TRUE,6,TextUnit_Character,5,docEnd,docEnd,0,docEnd,docEnd,FALSE
|
||||
FALSE,6,TextUnit_Character,-5,docEnd,docEndP1C,-5,docEndM5C,docEndM5C,FALSE
|
||||
FALSE,6,TextUnit_Character,-1,docEnd,docEndP1C,-1,docEndM1C,docEndM1C,FALSE
|
||||
FALSE,6,TextUnit_Character,0,docEnd,docEndP1C,0,docEnd,docEnd,FALSE
|
||||
FALSE,6,TextUnit_Character,1,docEnd,docEndP1C,0,docEnd,docEnd,FALSE
|
||||
FALSE,6,TextUnit_Character,5,docEnd,docEndP1C,0,docEnd,docEnd,FALSE
|
||||
TRUE,6,TextUnit_Line,-5,docEnd,docEnd,-5,docEndM5L,docEndM5L,FALSE
|
||||
TRUE,6,TextUnit_Line,-1,docEnd,docEnd,-1,docEndM1L,docEndM1L,FALSE
|
||||
TRUE,6,TextUnit_Line,0,docEnd,docEnd,0,docEnd,docEnd,FALSE
|
||||
TRUE,6,TextUnit_Line,1,docEnd,docEnd,0,docEnd,docEnd,FALSE
|
||||
TRUE,6,TextUnit_Line,5,docEnd,docEnd,0,docEnd,docEnd,FALSE
|
||||
FALSE,6,TextUnit_Line,-5,docEnd,docEndP1C,-5,docEndM5L,docEndM5L,FALSE
|
||||
FALSE,6,TextUnit_Line,-1,docEnd,docEndP1C,-1,docEndM1L,docEndM1L,FALSE
|
||||
FALSE,6,TextUnit_Line,0,docEnd,docEndP1C,0,docEnd,docEnd,FALSE
|
||||
FALSE,6,TextUnit_Line,1,docEnd,docEndP1C,0,docEnd,docEnd,FALSE
|
||||
FALSE,6,TextUnit_Line,5,docEnd,docEndP1C,0,docEnd,docEnd,FALSE
|
||||
TRUE,6,TextUnit_Document,-5,docEnd,docEnd,-1,origin,origin,FALSE
|
||||
TRUE,6,TextUnit_Document,-1,docEnd,docEnd,-1,origin,origin,FALSE
|
||||
TRUE,6,TextUnit_Document,0,docEnd,docEnd,0,docEnd,docEnd,FALSE
|
||||
TRUE,6,TextUnit_Document,1,docEnd,docEnd,0,docEnd,docEnd,FALSE
|
||||
TRUE,6,TextUnit_Document,5,docEnd,docEnd,0,docEnd,docEnd,FALSE
|
||||
FALSE,6,TextUnit_Document,-5,docEnd,docEndP1C,-1,origin,origin,FALSE
|
||||
FALSE,6,TextUnit_Document,-1,docEnd,docEndP1C,-1,origin,origin,FALSE
|
||||
FALSE,6,TextUnit_Document,0,docEnd,docEndP1C,0,docEnd,docEnd,FALSE
|
||||
FALSE,6,TextUnit_Document,1,docEnd,docEndP1C,0,docEnd,docEnd,FALSE
|
||||
FALSE,6,TextUnit_Document,5,docEnd,docEndP1C,0,docEnd,docEnd,FALSE
|
||||
TRUE,7,TextUnit_Character,-5,midEmptySpace,midEmptySpace,-5,docEndM5C,docEndM5C,FALSE
|
||||
TRUE,7,TextUnit_Character,-1,midEmptySpace,midEmptySpace,-1,docEndM1C,docEndM1C,FALSE
|
||||
TRUE,7,TextUnit_Character,0,midEmptySpace,midEmptySpace,0,docEnd,docEnd,FALSE
|
||||
TRUE,7,TextUnit_Character,1,midEmptySpace,midEmptySpace,0,docEnd,docEnd,FALSE
|
||||
TRUE,7,TextUnit_Character,5,midEmptySpace,midEmptySpace,0,docEnd,docEnd,FALSE
|
||||
FALSE,7,TextUnit_Character,-5,midEmptySpace,midEmptySpaceP1C,-5,docEndM5C,docEndM5C,FALSE
|
||||
FALSE,7,TextUnit_Character,-1,midEmptySpace,midEmptySpaceP1C,-1,docEndM1C,docEndM1C,FALSE
|
||||
FALSE,7,TextUnit_Character,0,midEmptySpace,midEmptySpaceP1C,0,docEnd,docEnd,FALSE
|
||||
FALSE,7,TextUnit_Character,1,midEmptySpace,midEmptySpaceP1C,0,docEnd,docEnd,FALSE
|
||||
FALSE,7,TextUnit_Character,5,midEmptySpace,midEmptySpaceP1C,0,docEnd,docEnd,FALSE
|
||||
TRUE,7,TextUnit_Line,-5,midEmptySpace,midEmptySpace,-5,docEndM5L,docEndM5L,FALSE
|
||||
TRUE,7,TextUnit_Line,-1,midEmptySpace,midEmptySpace,-1,docEndM1L,docEndM1L,FALSE
|
||||
TRUE,7,TextUnit_Line,0,midEmptySpace,midEmptySpace,0,docEnd,docEnd,FALSE
|
||||
TRUE,7,TextUnit_Line,1,midEmptySpace,midEmptySpace,0,docEnd,docEnd,FALSE
|
||||
TRUE,7,TextUnit_Line,5,midEmptySpace,midEmptySpace,0,docEnd,docEnd,FALSE
|
||||
FALSE,7,TextUnit_Line,-5,midEmptySpace,midEmptySpaceP1C,-5,docEndM5L,docEndM5L,FALSE
|
||||
FALSE,7,TextUnit_Line,-1,midEmptySpace,midEmptySpaceP1C,-1,docEndM1L,docEndM1L,FALSE
|
||||
FALSE,7,TextUnit_Line,0,midEmptySpace,midEmptySpaceP1C,0,docEnd,docEnd,FALSE
|
||||
FALSE,7,TextUnit_Line,1,midEmptySpace,midEmptySpaceP1C,0,docEnd,docEnd,FALSE
|
||||
FALSE,7,TextUnit_Line,5,midEmptySpace,midEmptySpaceP1C,0,docEnd,docEnd,FALSE
|
||||
TRUE,7,TextUnit_Document,-5,midEmptySpace,midEmptySpace,-1,origin,origin,FALSE
|
||||
TRUE,7,TextUnit_Document,-1,midEmptySpace,midEmptySpace,-1,origin,origin,FALSE
|
||||
TRUE,7,TextUnit_Document,0,midEmptySpace,midEmptySpace,0,docEnd,docEnd,FALSE
|
||||
TRUE,7,TextUnit_Document,1,midEmptySpace,midEmptySpace,0,docEnd,docEnd,FALSE
|
||||
TRUE,7,TextUnit_Document,5,midEmptySpace,midEmptySpace,0,docEnd,docEnd,FALSE
|
||||
FALSE,7,TextUnit_Document,-5,midEmptySpace,midEmptySpaceP1C,-1,origin,origin,FALSE
|
||||
FALSE,7,TextUnit_Document,-1,midEmptySpace,midEmptySpaceP1C,-1,origin,origin,FALSE
|
||||
FALSE,7,TextUnit_Document,0,midEmptySpace,midEmptySpaceP1C,0,docEnd,docEnd,FALSE
|
||||
FALSE,7,TextUnit_Document,1,midEmptySpace,midEmptySpaceP1C,0,docEnd,docEnd,FALSE
|
||||
FALSE,7,TextUnit_Document,5,midEmptySpace,midEmptySpaceP1C,0,docEnd,docEnd,FALSE
|
||||
TRUE,1,TextUnit_Word,-5,origin,origin,0,origin,origin,FALSE
|
||||
TRUE,1,TextUnit_Word,-1,origin,origin,0,origin,origin,FALSE
|
||||
TRUE,1,TextUnit_Word,0,origin,origin,0,origin,origin,FALSE
|
||||
TRUE,1,TextUnit_Word,1,origin,origin,1,segment1LmidTop,segment1LmidTop,FALSE
|
||||
TRUE,1,TextUnit_Word,5,origin,origin,5,segment0LmidTopP1L,segment0LmidTopP1L,FALSE
|
||||
FALSE,1,TextUnit_Word,-5,origin,originP1C,0,origin,segment1LmidTop,FALSE
|
||||
FALSE,1,TextUnit_Word,-1,origin,originP1C,0,origin,segment1LmidTop,FALSE
|
||||
FALSE,1,TextUnit_Word,0,origin,originP1C,0,origin,segment1LmidTop,FALSE
|
||||
FALSE,1,TextUnit_Word,1,origin,originP1C,1,segment1LmidTop,segment2LmidTop,FALSE
|
||||
FALSE,1,TextUnit_Word,5,origin,originP1C,5,segment0LmidTopP1L,segment1LmidTopP1L,FALSE
|
||||
TRUE,2,TextUnit_Word,-5,midTop,midTop,-3,origin,origin,TRUE
|
||||
TRUE,2,TextUnit_Word,-1,midTop,midTop,-1,segment2LmidTop,segment2LmidTop,TRUE
|
||||
TRUE,2,TextUnit_Word,0,midTop,midTop,0,midTop,midTop,FALSE
|
||||
TRUE,2,TextUnit_Word,1,midTop,midTop,1,segment3LmidTop,segment3LmidTop,FALSE
|
||||
TRUE,2,TextUnit_Word,5,midTop,midTop,5,segment2LmidTopP1L,segment2LmidTopP1L,FALSE
|
||||
FALSE,2,TextUnit_Word,-5,midTop,midTopP1C,-2,origin,segment1LmidTop,FALSE
|
||||
FALSE,2,TextUnit_Word,-1,midTop,midTopP1C,-1,segment1LmidTop,segment2LmidTop,FALSE
|
||||
FALSE,2,TextUnit_Word,0,midTop,midTopP1C,0,segment2LmidTop,segment3LmidTop,FALSE
|
||||
FALSE,2,TextUnit_Word,1,midTop,midTopP1C,1,segment3LmidTop,segment4LmidTop,FALSE
|
||||
FALSE,2,TextUnit_Word,5,midTop,midTopP1C,5,segment2LmidTopP1L,segment3LmidTopP1L,FALSE
|
||||
TRUE,3,TextUnit_Word,-5,midHistory,midHistory,-5,segment3LmidHistoryM1L,segment3LmidHistoryM1L,TRUE
|
||||
TRUE,3,TextUnit_Word,-1,midHistory,midHistory,-1,segment2LmidHistory,segment2LmidHistory,TRUE
|
||||
TRUE,3,TextUnit_Word,0,midHistory,midHistory,0,midHistory,midHistory,FALSE
|
||||
TRUE,3,TextUnit_Word,1,midHistory,midHistory,1,segment3LmidHistory,segment3LmidHistory,FALSE
|
||||
TRUE,3,TextUnit_Word,5,midHistory,midHistory,5,segment2LmidHistoryP1L,segment2LmidHistoryP1L,FALSE
|
||||
FALSE,3,TextUnit_Word,-5,midHistory,midHistoryP1C,-5,segment3LmidHistoryM1L,segment4LmidHistoryM1L,TRUE
|
||||
FALSE,3,TextUnit_Word,-1,midHistory,midHistoryP1C,-1,segment1LmidHistory,segment2LmidHistory,FALSE
|
||||
FALSE,3,TextUnit_Word,0,midHistory,midHistoryP1C,0,segment2LmidHistory,segment3LmidHistory,FALSE
|
||||
FALSE,3,TextUnit_Word,1,midHistory,midHistoryP1C,1,segment3LmidHistory,segment4LmidHistory,FALSE
|
||||
FALSE,3,TextUnit_Word,5,midHistory,midHistoryP1C,5,segment2LmidHistoryP1L,segment3LmidHistoryP1L,FALSE
|
||||
TRUE,4,TextUnit_Word,-5,midDocEnd,midDocEnd,-5,segment3LmidDocEndM1L,segment3LmidDocEndM1L,TRUE
|
||||
TRUE,4,TextUnit_Word,-1,midDocEnd,midDocEnd,-1,segment2LmidDocEnd,segment2LmidDocEnd,TRUE
|
||||
TRUE,4,TextUnit_Word,0,midDocEnd,midDocEnd,0,midDocEnd,midDocEnd,FALSE
|
||||
TRUE,4,TextUnit_Word,1,midDocEnd,midDocEnd,1,segment3LmidDocEnd,segment3LmidDocEnd,FALSE
|
||||
TRUE,4,TextUnit_Word,5,midDocEnd,midDocEnd,3,docEnd,docEnd,FALSE
|
||||
FALSE,4,TextUnit_Word,-5,midDocEnd,midDocEndP1C,-5,segment3LmidDocEndM1L,segment4LmidDocEndM1L,TRUE
|
||||
FALSE,4,TextUnit_Word,-1,midDocEnd,midDocEndP1C,-1,segment1LmidDocEnd,segment2LmidDocEnd,FALSE
|
||||
FALSE,4,TextUnit_Word,0,midDocEnd,midDocEndP1C,0,segment2LmidDocEnd,segment3LmidDocEnd,FALSE
|
||||
FALSE,4,TextUnit_Word,1,midDocEnd,midDocEndP1C,1,segment3LmidDocEnd,segment4LmidDocEnd,FALSE
|
||||
FALSE,4,TextUnit_Word,5,midDocEnd,midDocEndP1C,2,segment4LmidDocEnd,docEnd,FALSE
|
||||
TRUE,5,TextUnit_Word,-5,lastCharPos,lastCharPos,-5,lastCharPosLeft,lastCharPosLeft,TRUE
|
||||
TRUE,5,TextUnit_Word,-1,lastCharPos,lastCharPos,-1,segment4LmidDocEnd,segment4LmidDocEnd,TRUE
|
||||
TRUE,5,TextUnit_Word,0,lastCharPos,lastCharPos,0,lastCharPos,lastCharPos,FALSE
|
||||
TRUE,5,TextUnit_Word,1,lastCharPos,lastCharPos,1,docEnd,docEnd,FALSE
|
||||
TRUE,5,TextUnit_Word,5,lastCharPos,lastCharPos,1,docEnd,docEnd,FALSE
|
||||
FALSE,5,TextUnit_Word,-5,lastCharPos,lastCharPosP1C,-5,segment4LlastCharPosM1L,lastCharPosLeft,FALSE
|
||||
FALSE,5,TextUnit_Word,-1,lastCharPos,lastCharPosP1C,-1,segment3LmidDocEnd,segment4LmidDocEnd,FALSE
|
||||
FALSE,5,TextUnit_Word,0,lastCharPos,lastCharPosP1C,0,segment4LmidDocEnd,docEnd,FALSE
|
||||
FALSE,5,TextUnit_Word,1,lastCharPos,lastCharPosP1C,0,segment4LmidDocEnd,docEnd,FALSE
|
||||
FALSE,5,TextUnit_Word,5,lastCharPos,lastCharPosP1C,0,segment4LmidDocEnd,docEnd,FALSE
|
||||
TRUE,6,TextUnit_Word,-5,docEnd,docEnd,-5,midDocEndLeft,midDocEndLeft,TRUE
|
||||
TRUE,6,TextUnit_Word,-1,docEnd,docEnd,-1,segment4LmidDocEnd,segment4LmidDocEnd,TRUE
|
||||
TRUE,6,TextUnit_Word,0,docEnd,docEnd,0,docEnd,docEnd,FALSE
|
||||
TRUE,6,TextUnit_Word,1,docEnd,docEnd,0,docEnd,docEnd,FALSE
|
||||
TRUE,6,TextUnit_Word,5,docEnd,docEnd,0,docEnd,docEnd,FALSE
|
||||
FALSE,6,TextUnit_Word,-5,docEnd,docEndP1C,-5,midDocEndLeft,midDocEndLeft,TRUE
|
||||
FALSE,6,TextUnit_Word,-1,docEnd,docEndP1C,-1,segment4LmidDocEnd,segment4LmidDocEnd,TRUE
|
||||
FALSE,6,TextUnit_Word,0,docEnd,docEndP1C,0,docEnd,docEnd,FALSE
|
||||
FALSE,6,TextUnit_Word,1,docEnd,docEndP1C,0,docEnd,docEnd,FALSE
|
||||
FALSE,6,TextUnit_Word,5,docEnd,docEndP1C,0,docEnd,docEnd,FALSE
|
||||
TRUE,7,TextUnit_Word,-5,midEmptySpace,midEmptySpace,-5,midDocEndLeft,midDocEndLeft,TRUE
|
||||
TRUE,7,TextUnit_Word,-1,midEmptySpace,midEmptySpace,-1,segment4LmidDocEnd,segment4LmidDocEnd,TRUE
|
||||
TRUE,7,TextUnit_Word,0,midEmptySpace,midEmptySpace,0,docEnd,docEnd,FALSE
|
||||
TRUE,7,TextUnit_Word,1,midEmptySpace,midEmptySpace,0,docEnd,docEnd,FALSE
|
||||
TRUE,7,TextUnit_Word,5,midEmptySpace,midEmptySpace,0,docEnd,docEnd,FALSE
|
||||
FALSE,7,TextUnit_Word,-5,midEmptySpace,midEmptySpaceP1C,-5,midDocEndLeft,midDocEndLeft,TRUE
|
||||
FALSE,7,TextUnit_Word,-1,midEmptySpace,midEmptySpaceP1C,-1,segment4LmidDocEnd,segment4LmidDocEnd,TRUE
|
||||
FALSE,7,TextUnit_Word,0,midEmptySpace,midEmptySpaceP1C,0,docEnd,docEnd,FALSE
|
||||
FALSE,7,TextUnit_Word,1,midEmptySpace,midEmptySpaceP1C,0,docEnd,docEnd,FALSE
|
||||
FALSE,7,TextUnit_Word,5,midEmptySpace,midEmptySpaceP1C,0,docEnd,docEnd,FALSE
|
||||
TRUE,8,TextUnit_Word,-5,bufferEnd,bufferEnd,-5,midDocEndLeft,midDocEndLeft,TRUE
|
||||
TRUE,8,TextUnit_Word,-1,bufferEnd,bufferEnd,-1,segment4LmidDocEnd,segment4LmidDocEnd,TRUE
|
||||
TRUE,8,TextUnit_Word,0,bufferEnd,bufferEnd,0,docEnd,docEnd,FALSE
|
||||
TRUE,8,TextUnit_Word,1,bufferEnd,bufferEnd,0,docEnd,docEnd,FALSE
|
||||
TRUE,8,TextUnit_Word,5,bufferEnd,bufferEnd,0,docEnd,docEnd,FALSE
|
||||
FALSE,8,TextUnit_Word,-5,bufferEnd,endExclusive,-5,midDocEndLeft,midDocEndLeft,TRUE
|
||||
FALSE,8,TextUnit_Word,-1,bufferEnd,endExclusive,-1,segment4LmidDocEnd,segment4LmidDocEnd,TRUE
|
||||
FALSE,8,TextUnit_Word,0,bufferEnd,endExclusive,0,docEnd,docEnd,FALSE
|
||||
FALSE,8,TextUnit_Word,1,bufferEnd,endExclusive,0,docEnd,docEnd,FALSE
|
||||
FALSE,8,TextUnit_Word,5,bufferEnd,endExclusive,0,docEnd,docEnd,FALSE
|
||||
TRUE,9,TextUnit_Word,-5,endExclusive,endExclusive,-5,midDocEndLeft,midDocEndLeft,TRUE
|
||||
TRUE,9,TextUnit_Word,-1,endExclusive,endExclusive,-1,segment4LmidDocEnd,segment4LmidDocEnd,TRUE
|
||||
TRUE,9,TextUnit_Word,0,endExclusive,endExclusive,0,docEnd,docEnd,FALSE
|
||||
TRUE,9,TextUnit_Word,1,endExclusive,endExclusive,0,docEnd,docEnd,FALSE
|
||||
TRUE,9,TextUnit_Word,5,endExclusive,endExclusive,0,docEnd,docEnd,FALSE
|
||||
|
|
|
Loading…
Reference in a new issue