Skip to content

Commit 00b66c0

Browse files
committed
Move building tab profiles to TerminalPage
1 parent 4d1755e commit 00b66c0

8 files changed

Lines changed: 110 additions & 46 deletions

File tree

src/cascadia/TerminalApp/TerminalPage.cpp

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1067,6 +1067,54 @@ namespace winrt::TerminalApp::implementation
10671067
_newTabButton.Flyout(newTabFlyout);
10681068
}
10691069

1070+
// Method Description:
1071+
// - Builds the list of active profiles and raises SystemMenuNewTabProfilesChanged
1072+
// so the hosting window can populate its system menu "New Tab" submenu.
1073+
void TerminalPage::PopulateSystemMenuNewTabProfiles()
1074+
{
1075+
const auto activeProfiles = _settings.ActiveProfiles();
1076+
if (!activeProfiles || activeProfiles.Size() == 0)
1077+
{
1078+
return;
1079+
}
1080+
1081+
const auto defaultProfileGuid = _settings.GlobalSettings().DefaultProfile();
1082+
1083+
auto profileItems = winrt::single_threaded_vector<winrt::TerminalApp::SystemMenuNewTabProfileItem>();
1084+
1085+
for (uint32_t i = 0; i < activeProfiles.Size(); i++)
1086+
{
1087+
const auto profile = activeProfiles.GetAt(i);
1088+
auto displayName = profile.Name();
1089+
1090+
if (profile.Guid() == defaultProfileGuid)
1091+
{
1092+
displayName = displayName + L" (default)";
1093+
}
1094+
1095+
NewTerminalArgs newTerminalArgs{ gsl::narrow_cast<int32_t>(i) };
1096+
1097+
auto handler = winrt::TerminalApp::SystemMenuNewTabProfileHandler(
1098+
[weakThis{ get_weak() }, newTerminalArgs]() {
1099+
if (auto page{ weakThis.get() })
1100+
{
1101+
NewTabArgs newTabArgs{ newTerminalArgs };
1102+
ActionAndArgs actionAndArgs{ ShortcutAction::NewTab, newTabArgs };
1103+
page->_actionDispatch->DoAction(actionAndArgs);
1104+
}
1105+
});
1106+
1107+
auto item = winrt::make_self<winrt::TerminalApp::implementation::SystemMenuNewTabProfileItem>();
1108+
item->DisplayName(displayName);
1109+
item->Handler(handler);
1110+
profileItems.Append(*item);
1111+
}
1112+
1113+
auto args = winrt::make_self<winrt::TerminalApp::implementation::SystemMenuNewTabProfilesArgs>();
1114+
args->Profiles(profileItems);
1115+
SystemMenuNewTabProfilesChanged.raise(*this, *args);
1116+
}
1117+
10701118
// Method Description:
10711119
// - For a given list of tab menu entries, this method will create the corresponding
10721120
// list of flyout items. This is a recursive method that calls itself when it comes
@@ -3919,6 +3967,8 @@ namespace winrt::TerminalApp::implementation
39193967
_UpdateTabWidthMode();
39203968
_CreateNewTabFlyout();
39213969

3970+
PopulateSystemMenuNewTabProfiles();
3971+
39223972
// Reload the current value of alwaysOnTop from the settings file. This
39233973
// will let the user hot-reload this setting, but any runtime changes to
39243974
// the alwaysOnTop setting will be lost.

src/cascadia/TerminalApp/TerminalPage.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
#include "RenameWindowRequestedArgs.g.h"
1313
#include "RequestMoveContentArgs.g.h"
1414
#include "LaunchPositionRequest.g.h"
15+
#include "SystemMenuNewTabProfileItem.g.h"
16+
#include "SystemMenuNewTabProfilesArgs.g.h"
1517
#include "Toast.h"
1618

1719
#include "WindowsPackageManagerFactory.h"
@@ -77,6 +79,21 @@ namespace winrt::TerminalApp::implementation
7779
_TabIndex{ tabIndex } {};
7880
};
7981

82+
struct SystemMenuNewTabProfileItem : SystemMenuNewTabProfileItemT<SystemMenuNewTabProfileItem>
83+
{
84+
SystemMenuNewTabProfileItem() = default;
85+
86+
WINRT_PROPERTY(winrt::hstring, DisplayName, L"");
87+
WINRT_PROPERTY(winrt::TerminalApp::SystemMenuNewTabProfileHandler, Handler, nullptr);
88+
};
89+
90+
struct SystemMenuNewTabProfilesArgs : SystemMenuNewTabProfilesArgsT<SystemMenuNewTabProfilesArgs>
91+
{
92+
SystemMenuNewTabProfilesArgs() = default;
93+
94+
WINRT_PROPERTY(Windows::Foundation::Collections::IVector<winrt::TerminalApp::SystemMenuNewTabProfileItem>, Profiles, nullptr);
95+
};
96+
8097
struct LaunchPositionRequest : LaunchPositionRequestT<LaunchPositionRequest>
8198
{
8299
LaunchPositionRequest() = default;
@@ -176,6 +193,8 @@ namespace winrt::TerminalApp::implementation
176193

177194
uint32_t NumberOfTabs() const;
178195

196+
void PopulateSystemMenuNewTabProfiles();
197+
179198
til::property_changed_event PropertyChanged;
180199

181200
// -------------------------------- WinRT Events ---------------------------------
@@ -204,6 +223,8 @@ namespace winrt::TerminalApp::implementation
204223

205224
til::typed_event<IInspectable, winrt::TerminalApp::LaunchPositionRequest> RequestLaunchPosition;
206225

226+
til::typed_event<IInspectable, winrt::TerminalApp::SystemMenuNewTabProfilesArgs> SystemMenuNewTabProfilesChanged;
227+
207228
WINRT_OBSERVABLE_PROPERTY(winrt::Windows::UI::Xaml::Media::Brush, TitlebarBrush, PropertyChanged.raise, nullptr);
208229
WINRT_OBSERVABLE_PROPERTY(winrt::Windows::UI::Xaml::Media::Brush, FrameBrush, PropertyChanged.raise, nullptr);
209230

src/cascadia/TerminalApp/TerminalPage.idl

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,19 @@ namespace TerminalApp
5050
Microsoft.Terminal.Settings.Model.LaunchPosition Position;
5151
}
5252

53+
delegate void SystemMenuNewTabProfileHandler();
54+
55+
[default_interface] runtimeclass SystemMenuNewTabProfileItem
56+
{
57+
String DisplayName { get; };
58+
SystemMenuNewTabProfileHandler Handler { get; };
59+
};
60+
61+
[default_interface] runtimeclass SystemMenuNewTabProfilesArgs
62+
{
63+
IVector<SystemMenuNewTabProfileItem> Profiles { get; };
64+
};
65+
5366
[default_interface] runtimeclass TerminalPage : Windows.UI.Xaml.Controls.Page, Windows.UI.Xaml.Data.INotifyPropertyChanged, Microsoft.Terminal.UI.IDirectKeyListener
5467
{
5568
TerminalPage(WindowProperties properties, ContentManager manager);
@@ -103,5 +116,7 @@ namespace TerminalApp
103116
event Windows.Foundation.TypedEventHandler<Object, RequestReceiveContentArgs> RequestReceiveContent;
104117

105118
event Windows.Foundation.TypedEventHandler<Object, LaunchPositionRequest> RequestLaunchPosition;
119+
120+
event Windows.Foundation.TypedEventHandler<Object, SystemMenuNewTabProfilesArgs> SystemMenuNewTabProfilesChanged;
106121
}
107122
}

src/cascadia/TerminalApp/TerminalWindow.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,8 @@ namespace winrt::TerminalApp::implementation
217217
SystemMenuItemHandler(this, &TerminalWindow::_OpenSettingsUI));
218218
SystemMenuChangeRequested.raise(*this, *args);
219219

220+
_root->PopulateSystemMenuNewTabProfiles();
221+
220222
TraceLoggingWrite(
221223
g_hTerminalAppProvider,
222224
"WindowCreated",

src/cascadia/TerminalApp/TerminalWindow.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,8 @@ namespace winrt::TerminalApp::implementation
161161
til::typed_event<winrt::Windows::Foundation::IInspectable, winrt::TerminalApp::SettingsLoadEventArgs> SettingsChanged;
162162
til::typed_event<winrt::Windows::Foundation::IInspectable, winrt::Microsoft::Terminal::Control::WindowSizeChangedEventArgs> WindowSizeChanged;
163163

164+
FORWARDED_TYPED_EVENT(SystemMenuNewTabProfilesChanged, Windows::Foundation::IInspectable, winrt::TerminalApp::SystemMenuNewTabProfilesArgs, _root, SystemMenuNewTabProfilesChanged);
165+
164166
private:
165167
// If you add controls here, but forget to null them either here or in
166168
// the ctor, you're going to have a bad time. It'll mysteriously fail to

src/cascadia/TerminalApp/TerminalWindow.idl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@ namespace TerminalApp
129129
event Windows.Foundation.TypedEventHandler<Object, Object> OpenSystemMenu;
130130
event Windows.Foundation.TypedEventHandler<Object, Object> QuitRequested;
131131
event Windows.Foundation.TypedEventHandler<Object, TerminalApp.SystemMenuChangeArgs> SystemMenuChangeRequested;
132+
event Windows.Foundation.TypedEventHandler<Object, TerminalApp.SystemMenuNewTabProfilesArgs> SystemMenuNewTabProfilesChanged;
132133
event Windows.Foundation.TypedEventHandler<Object, Microsoft.Terminal.Control.ShowWindowArgs> ShowWindowChanged;
133134
event Windows.Foundation.TypedEventHandler<Object, Microsoft.Terminal.Control.WindowSizeChangedEventArgs> WindowSizeChanged;
134135

src/cascadia/WindowsTerminal/AppHost.cpp

Lines changed: 16 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,7 @@ void AppHost::Initialize()
233233
_revokers.AlwaysOnTopChanged = _windowLogic.AlwaysOnTopChanged(winrt::auto_revoke, { this, &AppHost::_AlwaysOnTopChanged });
234234
_revokers.RaiseVisualBell = _windowLogic.RaiseVisualBell(winrt::auto_revoke, { this, &AppHost::_RaiseVisualBell });
235235
_revokers.SystemMenuChangeRequested = _windowLogic.SystemMenuChangeRequested(winrt::auto_revoke, { this, &AppHost::_SystemMenuChangeRequested });
236+
_revokers.SystemMenuNewTabProfilesChanged = _windowLogic.SystemMenuNewTabProfilesChanged(winrt::auto_revoke, { this, &AppHost::_SystemMenuNewTabProfilesChanged });
236237
_revokers.ChangeMaximizeRequested = _windowLogic.ChangeMaximizeRequested(winrt::auto_revoke, { this, &AppHost::_ChangeMaximizeRequested });
237238
_revokers.RequestLaunchPosition = _windowLogic.RequestLaunchPosition(winrt::auto_revoke, { this, &AppHost::_HandleRequestLaunchPosition });
238239

@@ -304,8 +305,6 @@ void AppHost::Initialize()
304305
// set that content as well.
305306
_window->SetContent(_windowLogic.GetRoot());
306307
_window->OnAppInitialized();
307-
308-
_PopulateNewTabSubmenu();
309308
}
310309

311310
void AppHost::Close()
@@ -1024,9 +1023,6 @@ void AppHost::_HandleSettingsChanged(const winrt::Windows::Foundation::IInspecta
10241023
_window->SetAutoHideWindow(_windowLogic.AutoHideWindow());
10251024
_window->SetShowTabsFullscreen(_windowLogic.ShowTabsFullscreen());
10261025
_updateTheme();
1027-
1028-
// Rebuild the "New Tab" submenu in the system menu to reflect any profile changes
1029-
_PopulateNewTabSubmenu();
10301026
}
10311027

10321028
void AppHost::_IsQuakeWindowChanged(const winrt::Windows::Foundation::IInspectable&,
@@ -1097,67 +1093,42 @@ void AppHost::_SystemMenuChangeRequested(const winrt::Windows::Foundation::IInsp
10971093
}
10981094

10991095
// Method Description:
1100-
// - Populates a "New Tab" submenu in the system menu (Alt+Space) with
1101-
// the user's active profiles.
1096+
// - Handles the SystemMenuNewTabProfilesChanged event from the TerminalPage.
1097+
// Rebuilds the "New Tab" submenu in the system menu (Alt+Space) with items
1098+
// driven by the app layer's action engine.
11021099
// Arguments:
1103-
// - <none>
1100+
// - args: The SystemMenuNewTabProfilesArgs containing the new list of
1101+
// profiles to show in the "New Tab" submenu.
11041102
// Return Value:
11051103
// - <none>
1106-
void AppHost::_PopulateNewTabSubmenu()
1104+
void AppHost::_SystemMenuNewTabProfilesChanged(const winrt::Windows::Foundation::IInspectable&, const winrt::TerminalApp::SystemMenuNewTabProfilesArgs& args)
11071105
{
1108-
if (!_window || !_windowLogic)
1106+
if (!_window)
11091107
{
11101108
return;
11111109
}
11121110

11131111
_window->RemoveSystemSubMenu(L"New Tab");
11141112

1115-
const auto settings = _appLogic.Settings();
1116-
if (!settings)
1117-
{
1118-
return;
1119-
}
1120-
1121-
const auto activeProfiles = settings.ActiveProfiles();
1122-
if (!activeProfiles || activeProfiles.Size() == 0)
1113+
if (!args || !args.Profiles() || args.Profiles().Size() == 0)
11231114
{
11241115
return;
11251116
}
11261117

1127-
const auto defaultProfileGuid = settings.GlobalSettings().DefaultProfile();
1128-
11291118
std::vector<std::pair<winrt::hstring, winrt::delegate<void()>>> profileItems;
1130-
profileItems.reserve(activeProfiles.Size());
1119+
profileItems.reserve(args.Profiles().Size());
11311120

1132-
for (uint32_t i = 0; i < activeProfiles.Size(); i++)
1121+
for (const auto& item : args.Profiles())
11331122
{
1134-
const auto profile = activeProfiles.GetAt(i);
1135-
auto profileName = profile.Name();
1136-
1137-
if (profile.Guid() == defaultProfileGuid)
1138-
{
1139-
profileName = profileName + L" (default)";
1140-
}
1141-
1142-
auto callback = winrt::delegate<void()>([weakThis = weak_from_this(), name = winrt::hstring{ profileName }]() {
1143-
if (auto strongThis = weakThis.lock())
1123+
auto handler = item.Handler();
1124+
auto callback = winrt::delegate<void()>([handler]() {
1125+
if (handler)
11441126
{
1145-
if (strongThis->_windowLogic)
1146-
{
1147-
const std::array<winrt::hstring, 4> args{
1148-
winrt::hstring{ L"wt.exe" },
1149-
winrt::hstring{ L"new-tab" },
1150-
winrt::hstring{ L"--profile" },
1151-
name,
1152-
};
1153-
winrt::TerminalApp::CommandlineArgs cmdArgs;
1154-
cmdArgs.Commandline(args);
1155-
strongThis->_windowLogic.ExecuteCommandline(std::move(cmdArgs));
1156-
}
1127+
handler();
11571128
}
11581129
});
11591130

1160-
profileItems.emplace_back(std::move(profileName), std::move(callback));
1131+
profileItems.emplace_back(item.DisplayName(), std::move(callback));
11611132
}
11621133

11631134
_window->AddSystemSubMenu(L"New Tab", profileItems);

src/cascadia/WindowsTerminal/AppHost.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,8 @@ class AppHost : public std::enable_shared_from_this<AppHost>
131131
void _HandleRequestLaunchPosition(const winrt::Windows::Foundation::IInspectable& sender,
132132
winrt::TerminalApp::LaunchPositionRequest args);
133133

134-
void _PopulateNewTabSubmenu();
134+
void _SystemMenuNewTabProfilesChanged(const winrt::Windows::Foundation::IInspectable& sender,
135+
const winrt::TerminalApp::SystemMenuNewTabProfilesArgs& args);
135136

136137
// Helper struct. By putting these all into one struct, we can revoke them
137138
// all at once, by assigning _revokers to a fresh Revokers instance. That'll
@@ -162,6 +163,7 @@ class AppHost : public std::enable_shared_from_this<AppHost>
162163
winrt::TerminalApp::TerminalWindow::PropertyChanged_revoker PropertyChanged;
163164
winrt::TerminalApp::TerminalWindow::SettingsChanged_revoker SettingsChanged;
164165
winrt::TerminalApp::TerminalWindow::WindowSizeChanged_revoker WindowSizeChanged;
166+
winrt::TerminalApp::TerminalWindow::SystemMenuNewTabProfilesChanged_revoker SystemMenuNewTabProfilesChanged;
165167
} _revokers{};
166168

167169
// our IslandWindow is not a WinRT type. It can't make auto_revokers like

0 commit comments

Comments
 (0)