Skip to content
Merged
Show file tree
Hide file tree
Changes from 29 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
0ac796f
added split up/down/left/right context menus
dm17ryk Oct 29, 2024
d920a70
added build win x64 release script
dm17ryk Oct 29, 2024
7e41e64
moved split up/down/left/right context menus as submenu
dm17ryk Oct 30, 2024
58cbe3a
added to split with profile to up/down/left/right context menu, added…
dm17ryk Oct 30, 2024
6e2529b
fix startup directory for split with profile to up/down/left/right co…
dm17ryk Oct 30, 2024
c953b44
Merge branch 'microsoft:main' into main
dm17ryk Oct 30, 2024
ef25c63
update win x64 release build script
dm17ryk Oct 30, 2024
f900ea5
added translations for available languages
dm17ryk Oct 30, 2024
a57aff8
Update settings.json
dm17ryk Oct 30, 2024
ae838ec
Update settings.json
dm17ryk Oct 30, 2024
ab01742
removed newly added file
dm17ryk Oct 30, 2024
4ab861c
put back comments removed by mistake in TerminalPage.cpp, revert the …
dm17ryk Oct 30, 2024
409783a
revert .vscode/settings.json
dm17ryk Oct 30, 2024
e21c0b7
fixed Resources.resw SwapPaneText resource
dm17ryk Nov 1, 2024
12aad74
Update TerminalPage.cpp
dm17ryk Nov 1, 2024
f682222
the split pane entries exists twice on the second level, add a 'dupli…
dm17ryk Nov 2, 2024
3bcaa51
add visible with a separation line between the 'duplicate' entry and …
dm17ryk Nov 7, 2024
2c303d0
Update TerminalPage.cpp
dm17ryk Nov 7, 2024
0cabf20
fixed pane context menu separators
dm17ryk Nov 7, 2024
e6f0d6a
Update TerminalPage.cpp
dm17ryk Nov 7, 2024
526e0a9
fixed pane context menu separators, and formatting
dm17ryk Nov 7, 2024
52dbc03
Merge branch 'main' of github.com:dmitrykok/terminal
dm17ryk Nov 7, 2024
82aa44a
fixed formatting
dm17ryk Nov 7, 2024
bf1e135
update swap menu, show only available options
dm17ryk Nov 8, 2024
1d5a220
add find to context menu even if there is no selection
dm17ryk Nov 8, 2024
54c9c60
Update src/cascadia/TerminalApp/Resources/en-US/Resources.resw
dm17ryk Dec 11, 2024
9a936f4
cache the value of focusedProfile.Name() and focusedProfile.Icon(), c…
dm17ryk Dec 11, 2024
8cf4ad6
No need to manually override the value from the profile, with the val…
dm17ryk Dec 11, 2024
ea1dc48
pane split with profiles reworked, pane split context menu has submen…
dm17ryk Jan 26, 2025
0d9f9b1
Fix Find menu with selection
dm17ryk Mar 11, 2025
bd99d02
run code formatter
carlos-zamora May 13, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions src/cascadia/TerminalApp/Resources/en-US/Resources.resw
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,45 @@
<data name="SplitPaneText" xml:space="preserve">
<value>Split pane</value>
</data>
<data name="SplitPaneToolTipText" xml:space="preserve">
<value>Right click for split directions - right/down/up/left</value>
</data>
<data name="SplitPaneDownText" xml:space="preserve">
<value>Split pane down</value>
</data>
<data name="SplitPaneRightText" xml:space="preserve">
<value>Split pane right</value>
</data>
<data name="SplitPaneUpText" xml:space="preserve">
<value>Split pane up</value>
</data>
<data name="SplitPaneLeftText" xml:space="preserve">
<value>Split pane left</value>
</data>
<data name="SplitPaneDuplicateText" xml:space="preserve">
<value>Duplicate</value>
</data>
<data name="SwapPaneText" xml:space="preserve">
<value>Swap pane</value>
</data>
<data name="SwapPaneDownText" xml:space="preserve">
<value>Swap pane down</value>
</data>
<data name="SwapPaneRightText" xml:space="preserve">
<value>Swap pane right</value>
</data>
<data name="SwapPaneUpText" xml:space="preserve">
<value>Swap pane up</value>
</data>
<data name="SwapPaneLeftText" xml:space="preserve">
<value>Swap pane left</value>
</data>
<data name="TogglePaneZoomText" xml:space="preserve">
<value>Toggle pane zoom</value>
</data>
<data name="CloseOtherPanesText" xml:space="preserve">
<value>Close other panes</value>
</data>
<data name="SearchWebText" xml:space="preserve">
<value>Web search</value>
</data>
Expand Down
145 changes: 136 additions & 9 deletions src/cascadia/TerminalApp/TerminalPage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5034,9 +5034,48 @@ namespace winrt::TerminalApp::implementation
};
};

auto makeItem = [&menu, &makeCallback](const winrt::hstring& label,
auto makeItem = [&makeCallback](const winrt::hstring& label,
const winrt::hstring& icon,
const auto& action,
auto& targetMenu) {
AppBarButton button{};

if (!icon.empty())
{
auto iconElement = UI::IconPathConverter::IconWUX(icon);
Automation::AutomationProperties::SetAccessibilityView(iconElement, Automation::Peers::AccessibilityView::Raw);
button.Icon(iconElement);
}

button.Label(label);
button.Click(makeCallback(action));
targetMenu.SecondaryCommands().Append(button);
};

auto makeMenuItem = [](const winrt::hstring& label,
const winrt::hstring& icon,
const auto& subMenu,
auto& targetMenu) {
AppBarButton button{};

if (!icon.empty())
{
auto iconElement = UI::IconPathConverter::IconWUX(icon);
Automation::AutomationProperties::SetAccessibilityView(iconElement, Automation::Peers::AccessibilityView::Raw);
button.Icon(iconElement);
}

button.Label(label);
button.Flyout(subMenu);
targetMenu.SecondaryCommands().Append(button);
};

auto makeContextItem = [&makeCallback](const winrt::hstring& label,
const winrt::hstring& icon,
const auto& action) {
const winrt::hstring& tooltip,
const auto& action,
const auto& subMenu,
auto& targetMenu) {
AppBarButton button{};

if (!icon.empty())
Expand All @@ -5048,34 +5087,122 @@ namespace winrt::TerminalApp::implementation

button.Label(label);
button.Click(makeCallback(action));
menu.SecondaryCommands().Append(button);
WUX::Controls::ToolTipService::SetToolTip(button, box_value(tooltip));
button.ContextFlyout(subMenu);
targetMenu.SecondaryCommands().Append(button);
};

const auto focusedProfile = _GetFocusedTabImpl()->GetFocusedProfile();
auto separatorItem = AppBarSeparator{};
auto activeProfiles = _settings.ActiveProfiles();
auto activeProfileCount = gsl::narrow_cast<int>(activeProfiles.Size());
MUX::Controls::CommandBarFlyout splitPaneMenu{};

// Wire up each item to the action that should be performed. By actually
// connecting these to actions, we ensure the implementation is
// consistent. This also leaves room for customizing this menu with
// actions in the future.

makeItem(RS_(L"SplitPaneText"), L"\xF246", ActionAndArgs{ ShortcutAction::SplitPane, SplitPaneArgs{ SplitType::Duplicate } });
makeItem(RS_(L"DuplicateTabText"), L"\xF5ED", ActionAndArgs{ ShortcutAction::DuplicateTab, nullptr });
makeItem(RS_(L"DuplicateTabText"), L"\xF5ED", ActionAndArgs{ ShortcutAction::DuplicateTab, nullptr }, menu);

const auto focusedProfileName = focusedProfile.Name();
const auto focusedProfileIcon = focusedProfile.Icon();
const auto splitPaneDuplicateText = RS_(L"SplitPaneDuplicateText") + L" " + focusedProfileName; // SplitPaneDuplicateText

const auto splitPaneRightText = RS_(L"SplitPaneRightText");
const auto splitPaneDownText = RS_(L"SplitPaneDownText");
const auto splitPaneUpText = RS_(L"SplitPaneUpText");
const auto splitPaneLeftText = RS_(L"SplitPaneLeftText");
const auto splitPaneToolTipText = RS_(L"SplitPaneToolTipText");

MUX::Controls::CommandBarFlyout splitPaneContextMenu{};
makeItem(splitPaneRightText, focusedProfileIcon, ActionAndArgs{ ShortcutAction::SplitPane, SplitPaneArgs{ SplitType::Duplicate, SplitDirection::Right, .5, nullptr } }, splitPaneContextMenu);
makeItem(splitPaneDownText, focusedProfileIcon, ActionAndArgs{ ShortcutAction::SplitPane, SplitPaneArgs{ SplitType::Duplicate, SplitDirection::Down, .5, nullptr } }, splitPaneContextMenu);
makeItem(splitPaneUpText, focusedProfileIcon, ActionAndArgs{ ShortcutAction::SplitPane, SplitPaneArgs{ SplitType::Duplicate, SplitDirection::Up, .5, nullptr } }, splitPaneContextMenu);
makeItem(splitPaneLeftText, focusedProfileIcon, ActionAndArgs{ ShortcutAction::SplitPane, SplitPaneArgs{ SplitType::Duplicate, SplitDirection::Left, .5, nullptr } }, splitPaneContextMenu);

makeContextItem(splitPaneDuplicateText, focusedProfileIcon, splitPaneToolTipText, ActionAndArgs{ ShortcutAction::SplitPane, SplitPaneArgs{ SplitType::Duplicate, SplitDirection::Automatic, .5, nullptr } }, splitPaneContextMenu, splitPaneMenu);

// add menu separator
const auto separatorAutoItem = AppBarSeparator{};

splitPaneMenu.SecondaryCommands().Append(separatorAutoItem);

for (auto profileIndex = 0; profileIndex < activeProfileCount; profileIndex++)
{
const auto profile = activeProfiles.GetAt(profileIndex);
const auto profileName = profile.Name();
const auto profileIcon = profile.Icon();

NewTerminalArgs args{};
args.Profile(profileName);

MUX::Controls::CommandBarFlyout splitPaneContextMenu{};
makeItem(splitPaneRightText, profileIcon, ActionAndArgs{ ShortcutAction::SplitPane, SplitPaneArgs{ SplitType::Manual, SplitDirection::Right, .5, args } }, splitPaneContextMenu);
makeItem(splitPaneDownText, profileIcon, ActionAndArgs{ ShortcutAction::SplitPane, SplitPaneArgs{ SplitType::Manual, SplitDirection::Down, .5, args } }, splitPaneContextMenu);
makeItem(splitPaneUpText, profileIcon, ActionAndArgs{ ShortcutAction::SplitPane, SplitPaneArgs{ SplitType::Manual, SplitDirection::Up, .5, args } }, splitPaneContextMenu);
makeItem(splitPaneLeftText, profileIcon, ActionAndArgs{ ShortcutAction::SplitPane, SplitPaneArgs{ SplitType::Manual, SplitDirection::Left, .5, args } }, splitPaneContextMenu);

makeContextItem(profileName, profileIcon, splitPaneToolTipText, ActionAndArgs{ ShortcutAction::SplitPane, SplitPaneArgs{ SplitType::Manual, SplitDirection::Automatic, .5, args } }, splitPaneContextMenu, splitPaneMenu);
}

makeMenuItem(RS_(L"SplitPaneText"), L"\xF246", splitPaneMenu, menu);

// Only wire up "Close Pane" if there's multiple panes.
if (_GetFocusedTabImpl()->GetLeafPaneCount() > 1)
{
makeItem(RS_(L"PaneClose"), L"\xE89F", ActionAndArgs{ ShortcutAction::ClosePane, nullptr });
MUX::Controls::CommandBarFlyout swapPaneMenu{};
const auto rootPane = _GetFocusedTabImpl()->GetRootPane();
const auto mruPanes = _GetFocusedTabImpl()->GetMruPanes();
auto activePane = _GetFocusedTabImpl()->GetActivePane();
rootPane->WalkTree([&](auto p) {
if (const auto& c{ p->GetTerminalControl() })
{
if (c == control)
{
activePane = p;
}
}
});

if (auto neighbor = rootPane->NavigateDirection(activePane, FocusDirection::Down, mruPanes))
{
makeItem(RS_(L"SwapPaneDownText"), neighbor->GetProfile().Icon(), ActionAndArgs{ ShortcutAction::SwapPane, SwapPaneArgs{ FocusDirection::Down } }, swapPaneMenu);
}

if (auto neighbor = rootPane->NavigateDirection(activePane, FocusDirection::Right, mruPanes))
{
makeItem(RS_(L"SwapPaneRightText"), neighbor->GetProfile().Icon(), ActionAndArgs{ ShortcutAction::SwapPane, SwapPaneArgs{ FocusDirection::Right } }, swapPaneMenu);
}

if (auto neighbor = rootPane->NavigateDirection(activePane, FocusDirection::Up, mruPanes))
{
makeItem(RS_(L"SwapPaneUpText"), neighbor->GetProfile().Icon(), ActionAndArgs{ ShortcutAction::SwapPane, SwapPaneArgs{ FocusDirection::Up } }, swapPaneMenu);
}

if (auto neighbor = rootPane->NavigateDirection(activePane, FocusDirection::Left, mruPanes))
{
makeItem(RS_(L"SwapPaneLeftText"), neighbor->GetProfile().Icon(), ActionAndArgs{ ShortcutAction::SwapPane, SwapPaneArgs{ FocusDirection::Left } }, swapPaneMenu);
}

makeMenuItem(RS_(L"SwapPaneText"), L"\xF1CB", swapPaneMenu, menu);

makeItem(RS_(L"TogglePaneZoomText"), L"\xE8A3", ActionAndArgs{ ShortcutAction::TogglePaneZoom, nullptr }, menu);
makeItem(RS_(L"CloseOtherPanesText"), L"\xE89F", ActionAndArgs{ ShortcutAction::CloseOtherPanes, nullptr }, menu);
makeItem(RS_(L"PaneClose"), L"\xE89F", ActionAndArgs{ ShortcutAction::ClosePane, nullptr }, menu);
}

if (control.ConnectionState() >= ConnectionState::Closed)
{
makeItem(RS_(L"RestartConnectionText"), L"\xE72C", ActionAndArgs{ ShortcutAction::RestartConnection, nullptr });
makeItem(RS_(L"RestartConnectionText"), L"\xE72C", ActionAndArgs{ ShortcutAction::RestartConnection, nullptr }, menu);
}

if (withSelection)
{
makeItem(RS_(L"SearchWebText"), L"\xF6FA", ActionAndArgs{ ShortcutAction::SearchForText, nullptr });
makeItem(RS_(L"SearchWebText"), L"\xF6FA", ActionAndArgs{ ShortcutAction::SearchForText, nullptr }, menu);
}

makeItem(RS_(L"TabClose"), L"\xE711", ActionAndArgs{ ShortcutAction::CloseTab, CloseTabArgs{ _GetFocusedTabIndex().value() } });
makeItem(RS_(L"TabClose"), L"\xE711", ActionAndArgs{ ShortcutAction::CloseTab, CloseTabArgs{ _GetFocusedTabIndex().value() } }, menu);
}

void TerminalPage::_PopulateQuickFixMenu(const TermControl& control,
Expand Down
1 change: 1 addition & 0 deletions src/cascadia/TerminalApp/TerminalTab.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ namespace winrt::TerminalApp::implementation
winrt::TerminalApp::TaskbarState GetCombinedTaskbarState() const;

std::shared_ptr<Pane> GetRootPane() const { return _rootPane; }
std::vector<uint32_t> GetMruPanes() const { return _mruPanes; }

winrt::TerminalApp::TerminalTabStatus TabStatus()
{
Expand Down
16 changes: 8 additions & 8 deletions src/cascadia/TerminalControl/TermControl.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@
x:Uid="SelectOutputButton"
Click="_SelectOutputHandler"
Icon="AlignLeft" />
<AppBarButton x:Name="SearchCommandButton"
x:Uid="SearchCommandButton"
Click="_SearchCommandHandler"
Icon="Find" />
</mux:CommandBarFlyout.SecondaryCommands>
</mux:CommandBarFlyout>

Expand All @@ -64,10 +68,6 @@
Click="_PasteCommandHandler"
Icon="Paste" />
<mux:CommandBarFlyout.SecondaryCommands>
<AppBarButton x:Name="SearchCommandButton"
x:Uid="SearchCommandButton"
Click="_SearchCommandHandler"
Icon="Find" />
<AppBarButton x:Name="SelectCommandWithSelectionButton"
x:Uid="SelectCommandWithSelectionButton"
Click="_SelectCommandHandler">
Expand All @@ -89,17 +89,17 @@
12dips. This is harder for folks to hit with the mouse, and isn't
consistent with the rest of the scrollbars on the platform (as much
as they can be).

To work around this, we have to entirely copy the template for the
ScrollBar into our XAML file. We're then also re-defining
ScrollBarSize here to 16, so that the new template will pick up on
the new value.

This is kinda a pain, and we have to be careful to be sure to ingest
an updated version of the template any time we update MUX. The
latest ControlsV2 version of the template can be found at:
https://github.com/microsoft/microsoft-ui-xaml/blob/main/dev/CommonStyles/ScrollBar_themeresources.xaml#L218

Additionally we have:
* removed the corner radius, because that should be flush
with the top of the window above the TermControl.
Expand All @@ -108,7 +108,7 @@
the Win11-style WinUI ScrollView. If you also have the "Always show scrollbars" setting enabled in
the settings app (do it if you haven't already), it avoids any and all animations during startup which
makes the app start feel noticeably better and also shaves off another ~167ms of our "busy time".

We're also planning on making this adjustable in the future
(GH#9218), where we might need this anyways.
-->
Expand Down
Loading