Skip to content

Commit

Permalink
PRE-MERGE #14935 Enable tearing out tabs to create new windows
Browse files Browse the repository at this point in the history
  • Loading branch information
carlos-zamora committed Mar 3, 2023
2 parents 599b550 + 796a02e commit dbdc672
Show file tree
Hide file tree
Showing 88 changed files with 5,308 additions and 3,382 deletions.
1 change: 1 addition & 0 deletions .github/actions/spelling/allow/apis.txt
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@ rcx
REGCLS
RETURNCMD
rfind
RLO
ROOTOWNER
roundf
RSHIFT
Expand Down
4 changes: 2 additions & 2 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"C_Cpp.loggingLevel": "None",
"files.associations": {
"xstring": "cpp",
"*.idl": "cpp",
"*.idl": "midl3",
"array": "cpp",
"future": "cpp",
"istream": "cpp",
Expand Down Expand Up @@ -106,4 +106,4 @@
"**/packages/**": true,
"**/Generated Files/**": true
}
}
}
7 changes: 6 additions & 1 deletion doc/cascadia/profiles.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -1822,7 +1822,7 @@
"name": {
"type": "string",
"description": "The name of the theme. This will be displayed in the settings UI.",
"not": {
"not": {
"enum": [ "light", "dark", "system" ]
}
},
Expand Down Expand Up @@ -2092,6 +2092,11 @@
"description": "When set to true, the terminal will focus the pane on mouse hover.",
"type": "boolean"
},
"compatibility.isolatedMode": {
"default": false,
"description": "When set to true, Terminal windows will not be able to interact with each other (including global hotkeys, tab drag/drop, running commandlines in existing windows, etc.). This is a compatibility escape hatch for users who are running into certain windowing issues.",
"type": "boolean"
},
"copyFormatting": {
"default": true,
"description": "When set to `true`, the color and font formatting of selected text is also copied to your clipboard. When set to `false`, only plain text is copied to your clipboard. An array of specific formats can also be used. Supported array values include `html` and `rtf`. Plain text is always copied.",
Expand Down
45 changes: 27 additions & 18 deletions src/cascadia/LocalTests_TerminalApp/SettingsTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -164,8 +164,9 @@ namespace TerminalAppLocalTests
VERIFY_ARE_EQUAL(L"${profile.name}", realArgs.TerminalArgs().Profile());
}

auto expandedCommands = winrt::TerminalApp::implementation::TerminalPage::_ExpandCommands(nameMap, settings.ActiveProfiles().GetView(), settings.GlobalSettings().ColorSchemes());
_logCommandNames(expandedCommands.GetView());
settings.ExpandCommands();
const auto& expandedCommands{ settings.GlobalSettings().ActionMap().ExpandedCommands() };
_logCommandNames(expandedCommands);

VERIFY_ARE_EQUAL(0u, settings.Warnings().Size());
VERIFY_ARE_EQUAL(3u, expandedCommands.Size());
Expand Down Expand Up @@ -287,8 +288,9 @@ namespace TerminalAppLocalTests
VERIFY_ARE_EQUAL(L"${profile.name}", realArgs.TerminalArgs().Profile());
}

auto expandedCommands = winrt::TerminalApp::implementation::TerminalPage::_ExpandCommands(nameMap, settings.ActiveProfiles().GetView(), settings.GlobalSettings().ColorSchemes());
_logCommandNames(expandedCommands.GetView());
settings.ExpandCommands();
const auto& expandedCommands{ settings.GlobalSettings().ActionMap().ExpandedCommands() };
_logCommandNames(expandedCommands);

VERIFY_ARE_EQUAL(0u, settings.Warnings().Size());
VERIFY_ARE_EQUAL(3u, expandedCommands.Size());
Expand Down Expand Up @@ -412,8 +414,9 @@ namespace TerminalAppLocalTests
VERIFY_ARE_EQUAL(L"${profile.name}", realArgs.TerminalArgs().Profile());
}

auto expandedCommands = winrt::TerminalApp::implementation::TerminalPage::_ExpandCommands(nameMap, settings.ActiveProfiles().GetView(), settings.GlobalSettings().ColorSchemes());
_logCommandNames(expandedCommands.GetView());
settings.ExpandCommands();
const auto& expandedCommands{ settings.GlobalSettings().ActionMap().ExpandedCommands() };
_logCommandNames(expandedCommands);

VERIFY_ARE_EQUAL(0u, settings.Warnings().Size());
VERIFY_ARE_EQUAL(3u, expandedCommands.Size());
Expand Down Expand Up @@ -527,8 +530,9 @@ namespace TerminalAppLocalTests
VERIFY_ARE_EQUAL(0u, settings.Warnings().Size());
VERIFY_ARE_EQUAL(3u, settings.ActiveProfiles().Size());

auto expandedCommands = winrt::TerminalApp::implementation::TerminalPage::_ExpandCommands(settings.ActionMap().NameMap(), settings.ActiveProfiles().GetView(), settings.GlobalSettings().ColorSchemes());
_logCommandNames(expandedCommands.GetView());
settings.ExpandCommands();
const auto& expandedCommands{ settings.GlobalSettings().ActionMap().ExpandedCommands() };
_logCommandNames(expandedCommands);

VERIFY_ARE_EQUAL(0u, settings.Warnings().Size());
VERIFY_ARE_EQUAL(1u, expandedCommands.Size());
Expand Down Expand Up @@ -621,8 +625,9 @@ namespace TerminalAppLocalTests
VERIFY_ARE_EQUAL(0u, settings.Warnings().Size());
VERIFY_ARE_EQUAL(3u, settings.ActiveProfiles().Size());

auto expandedCommands = winrt::TerminalApp::implementation::TerminalPage::_ExpandCommands(settings.ActionMap().NameMap(), settings.ActiveProfiles().GetView(), settings.GlobalSettings().ColorSchemes());
_logCommandNames(expandedCommands.GetView());
settings.ExpandCommands();
const auto& expandedCommands{ settings.GlobalSettings().ActionMap().ExpandedCommands() };
_logCommandNames(expandedCommands);

VERIFY_ARE_EQUAL(0u, settings.Warnings().Size());
VERIFY_ARE_EQUAL(1u, expandedCommands.Size());
Expand Down Expand Up @@ -744,8 +749,9 @@ namespace TerminalAppLocalTests
VERIFY_ARE_EQUAL(0u, settings.Warnings().Size());
VERIFY_ARE_EQUAL(3u, settings.ActiveProfiles().Size());

auto expandedCommands = winrt::TerminalApp::implementation::TerminalPage::_ExpandCommands(settings.ActionMap().NameMap(), settings.ActiveProfiles().GetView(), settings.GlobalSettings().ColorSchemes());
_logCommandNames(expandedCommands.GetView());
settings.ExpandCommands();
const auto& expandedCommands{ settings.GlobalSettings().ActionMap().ExpandedCommands() };
_logCommandNames(expandedCommands);

VERIFY_ARE_EQUAL(0u, settings.Warnings().Size());

Expand Down Expand Up @@ -880,8 +886,9 @@ namespace TerminalAppLocalTests
VERIFY_ARE_EQUAL(0u, settings.Warnings().Size());
VERIFY_ARE_EQUAL(3u, settings.ActiveProfiles().Size());

auto expandedCommands = winrt::TerminalApp::implementation::TerminalPage::_ExpandCommands(settings.ActionMap().NameMap(), settings.ActiveProfiles().GetView(), settings.GlobalSettings().ColorSchemes());
_logCommandNames(expandedCommands.GetView());
settings.ExpandCommands();
const auto& expandedCommands{ settings.GlobalSettings().ActionMap().ExpandedCommands() };
_logCommandNames(expandedCommands);

VERIFY_ARE_EQUAL(0u, settings.Warnings().Size());
VERIFY_ARE_EQUAL(1u, expandedCommands.Size());
Expand Down Expand Up @@ -982,8 +989,9 @@ namespace TerminalAppLocalTests
VERIFY_ARE_EQUAL(0u, settings.Warnings().Size());
VERIFY_ARE_EQUAL(3u, settings.ActiveProfiles().Size());

auto expandedCommands = winrt::TerminalApp::implementation::TerminalPage::_ExpandCommands(settings.ActionMap().NameMap(), settings.ActiveProfiles().GetView(), settings.GlobalSettings().ColorSchemes());
_logCommandNames(expandedCommands.GetView());
settings.ExpandCommands();
const auto& expandedCommands{ settings.GlobalSettings().ActionMap().ExpandedCommands() };
_logCommandNames(expandedCommands);

VERIFY_ARE_EQUAL(0u, settings.Warnings().Size());
VERIFY_ARE_EQUAL(1u, expandedCommands.Size());
Expand Down Expand Up @@ -1205,8 +1213,9 @@ namespace TerminalAppLocalTests
VERIFY_ARE_EQUAL(L"${scheme.name}", realArgs.TerminalArgs().Profile());
}

auto expandedCommands = winrt::TerminalApp::implementation::TerminalPage::_ExpandCommands(nameMap, settings.ActiveProfiles().GetView(), settings.GlobalSettings().ColorSchemes());
_logCommandNames(expandedCommands.GetView());
settings.ExpandCommands();
const auto& expandedCommands{ settings.GlobalSettings().ActionMap().ExpandedCommands() };
_logCommandNames(expandedCommands);

VERIFY_ARE_EQUAL(3u, expandedCommands.Size());

Expand Down
27 changes: 23 additions & 4 deletions src/cascadia/LocalTests_TerminalApp/TabTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,17 @@ namespace TerminalAppLocalTests
// an updated TAEF that will let us install framework packages when the test
// package is deployed. Until then, these tests won't deploy in CI.

struct WindowProperties : winrt::implements<WindowProperties, winrt::TerminalApp::IWindowProperties>
{
WINRT_PROPERTY(winrt::hstring, WindowName);
WINRT_PROPERTY(uint64_t, WindowId);
WINRT_PROPERTY(winrt::hstring, WindowNameForDisplay);
WINRT_PROPERTY(winrt::hstring, WindowIdForDisplay);

public:
bool IsQuakeWindow() { return _WindowName == L"_quake"; };
};

class TabTests
{
// For this set of tests, we need to activate some XAML content. For
Expand Down Expand Up @@ -110,6 +121,7 @@ namespace TerminalAppLocalTests
void _initializeTerminalPage(winrt::com_ptr<winrt::TerminalApp::implementation::TerminalPage>& page,
CascadiaSettings initialSettings);
winrt::com_ptr<winrt::TerminalApp::implementation::TerminalPage> _commonSetup();
winrt::com_ptr<WindowProperties> _windowProperties;
};

template<typename TFunction>
Expand Down Expand Up @@ -239,11 +251,15 @@ namespace TerminalAppLocalTests
// it's weird.
winrt::TerminalApp::TerminalPage projectedPage{ nullptr };

_windowProperties = winrt::make_self<WindowProperties>();
winrt::TerminalApp::IWindowProperties iProps{ *_windowProperties };

Log::Comment(NoThrowString().Format(L"Construct the TerminalPage"));
auto result = RunOnUIThread([&projectedPage, &page, initialSettings]() {
auto result = RunOnUIThread([&projectedPage, &page, initialSettings, iProps]() {
projectedPage = winrt::TerminalApp::TerminalPage();
page.copy_from(winrt::get_self<winrt::TerminalApp::implementation::TerminalPage>(projectedPage));
page->_settings = initialSettings;
page->WindowProperties(iProps);
});
VERIFY_SUCCEEDED(result);

Expand Down Expand Up @@ -1242,10 +1258,13 @@ namespace TerminalAppLocalTests
END_TEST_METHOD_PROPERTIES()

auto page = _commonSetup();
page->RenameWindowRequested([&page](auto&&, const winrt::TerminalApp::RenameWindowRequestedArgs args) {
page->RenameWindowRequested([&page, this](auto&&, const winrt::TerminalApp::RenameWindowRequestedArgs args) {
// In the real terminal, this would bounce up to the monarch and
// come back down. Instead, immediately call back and set the name.
page->WindowName(args.ProposedName());
//
// This replicates how TerminalWindow works
_windowProperties->WindowName(args.ProposedName());
page->WindowNameChanged();
});

auto windowNameChanged = false;
Expand All @@ -1260,7 +1279,7 @@ namespace TerminalAppLocalTests
page->_RequestWindowRename(winrt::hstring{ L"Foo" });
});
TestOnUIThread([&]() {
VERIFY_ARE_EQUAL(L"Foo", page->_WindowName);
VERIFY_ARE_EQUAL(L"Foo", page->WindowName());
VERIFY_IS_TRUE(windowNameChanged,
L"The window name should have changed, and we should have raised a notification that WindowNameForDisplay changed");
});
Expand Down
113 changes: 113 additions & 0 deletions src/cascadia/Remoting/Monarch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include "ProposeCommandlineResult.h"

#include "Monarch.g.cpp"
#include "WindowRequestedArgs.g.cpp"
#include "../../types/inc/utils.hpp"

using namespace winrt;
Expand Down Expand Up @@ -687,6 +688,11 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
case WindowingBehaviorUseName:
windowID = _lookupPeasantIdForName(targetWindowName);
break;
case WindowingBehaviorUseNone:
// This should be impossible. The if statement above should have
// prevented WindowingBehaviorUseNone from falling in here.
// Explode, because this is a programming error.
THROW_HR(E_UNEXPECTED);
default:
windowID = ::base::saturated_cast<uint64_t>(targetWindow);
break;
Expand Down Expand Up @@ -724,6 +730,8 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
result->WindowName(targetWindowName);
result->ShouldCreateWindow(true);

_RequestNewWindowHandlers(*this, *winrt::make_self<WindowRequestedArgs>(*result, args));

// If this fails, it'll be logged in the following
// TraceLoggingWrite statement, with succeeded=false
}
Expand Down Expand Up @@ -759,9 +767,20 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
auto result{ winrt::make_self<Remoting::implementation::ProposeCommandlineResult>(true) };
result->Id(windowID);
result->WindowName(targetWindowName);

_RequestNewWindowHandlers(*this, *winrt::make_self<WindowRequestedArgs>(*result, args));

return *result;
}
}
else if (targetWindow == WindowingBehaviorUseNone)
{
// In this case, the targetWindow was UseNone, which means that we
// want to make a message box, but otherwise not make a Terminal
// window.
auto result = winrt::make_self<Remoting::implementation::ProposeCommandlineResult>(false);
return *result;
}

// If we get here, we couldn't find an existing window. Make a new one.
TraceLoggingWrite(g_hRemotingProvider,
Expand All @@ -773,6 +792,9 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
// In this case, no usable ID was provided. Return { true, nullopt }
auto result = winrt::make_self<Remoting::implementation::ProposeCommandlineResult>(true);
result->WindowName(targetWindowName);

_RequestNewWindowHandlers(*this, *winrt::make_self<WindowRequestedArgs>(*result, args));

return *result;
}

Expand Down Expand Up @@ -1034,4 +1056,95 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation

return winrt::single_threaded_vector(std::move(vec));
}

void Monarch::RequestMoveContent(winrt::hstring window,
winrt::hstring content,
uint32_t tabIndex,
Windows::Foundation::IReference<Windows::Foundation::Rect> windowBounds)
{
TraceLoggingWrite(g_hRemotingProvider,
"Monarch_MoveContent_Requested",
TraceLoggingWideString(window.c_str(), "window", "The name of the window we tried to move to"),
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE),
TraceLoggingKeyword(TIL_KEYWORD_TRACE));

uint64_t windowId = _lookupPeasantIdForName(window);
if (windowId == 0)
{
// Try the name as an integer ID
uint32_t temp;
if (!Utils::StringToUint(window.c_str(), temp))
{
TraceLoggingWrite(g_hRemotingProvider,
"Monarch_MoveContent_FailedToParseId",
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE),
TraceLoggingKeyword(TIL_KEYWORD_TRACE));
}
else
{
windowId = temp;
}
}

if (auto targetPeasant{ _getPeasant(windowId) })
{
auto request = winrt::make_self<implementation::AttachRequest>(content, tabIndex);
targetPeasant.AttachContentToWindow(*request);
TraceLoggingWrite(g_hRemotingProvider,
"Monarch_MoveContent_Completed",
TraceLoggingInt64(windowId, "windowId", "The ID of the peasant which we sent the content to"),
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE),
TraceLoggingKeyword(TIL_KEYWORD_TRACE));
}
else
{
TraceLoggingWrite(g_hRemotingProvider,
"Monarch_MoveContent_NoWindow",
TraceLoggingInt64(windowId, "windowId", "We could not find a peasant with this ID"),
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE),
TraceLoggingKeyword(TIL_KEYWORD_TRACE));

// In the case where window couldn't be found, then create a window
// for that name / ID.
//
// Don't let the window literally be named "-1", because that's silly
auto request = winrt::make_self<implementation::WindowRequestedArgs>(window == L"-1" ? L"" : window,
content,
windowBounds);
_RequestNewWindowHandlers(*this, *request);
}
}

// Very similar to the above. Someone came and told us that they were the target of a drag/drop, and they know who started it.
// We will go tell the person who started it that they should send that target the content which was dragged.
void Monarch::RequestSendContent(Remoting::RequestReceiveContentArgs args)
{
TraceLoggingWrite(g_hRemotingProvider,
"Monarch_SendContent_Requested",
TraceLoggingUInt64(args.SourceWindow(), "source", "The window which started the drag"),
TraceLoggingUInt64(args.TargetWindow(), "target", "The window which was the target of the drop"),
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE),
TraceLoggingKeyword(TIL_KEYWORD_TRACE));

if (auto senderPeasant{ _getPeasant(args.SourceWindow()) })
{
senderPeasant.SendContent(args);

TraceLoggingWrite(g_hRemotingProvider,
"Monarch_SendContent_Completed",
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE),
TraceLoggingKeyword(TIL_KEYWORD_TRACE));
}
else
{
// We couldn't find the peasant that started the drag. Well that
// sure is weird, but that would indicate that the sender closed
// after starting the drag. No matter. We can just do nothing.

TraceLoggingWrite(g_hRemotingProvider,
"Monarch_SendContent_NoWindow",
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE),
TraceLoggingKeyword(TIL_KEYWORD_TRACE));
}
}
}
Loading

0 comments on commit dbdc672

Please sign in to comment.