@@ -4988,9 +4988,48 @@ namespace winrt::TerminalApp::implementation
49884988 };
49894989 };
49904990
4991- auto makeItem = [&menu, &makeCallback](const winrt::hstring& label,
4991+ auto makeItem = [&makeCallback](const winrt::hstring& label,
4992+ const winrt::hstring& icon,
4993+ const auto & action,
4994+ auto & targetMenu) {
4995+ AppBarButton button{};
4996+
4997+ if (!icon.empty ())
4998+ {
4999+ auto iconElement = UI::IconPathConverter::IconWUX (icon);
5000+ Automation::AutomationProperties::SetAccessibilityView (iconElement, Automation::Peers::AccessibilityView::Raw);
5001+ button.Icon (iconElement);
5002+ }
5003+
5004+ button.Label (label);
5005+ button.Click (makeCallback (action));
5006+ targetMenu.SecondaryCommands ().Append (button);
5007+ };
5008+
5009+ auto makeMenuItem = [](const winrt::hstring& label,
5010+ const winrt::hstring& icon,
5011+ const auto & subMenu,
5012+ auto & targetMenu) {
5013+ AppBarButton button{};
5014+
5015+ if (!icon.empty ())
5016+ {
5017+ auto iconElement = UI::IconPathConverter::IconWUX (icon);
5018+ Automation::AutomationProperties::SetAccessibilityView (iconElement, Automation::Peers::AccessibilityView::Raw);
5019+ button.Icon (iconElement);
5020+ }
5021+
5022+ button.Label (label);
5023+ button.Flyout (subMenu);
5024+ targetMenu.SecondaryCommands ().Append (button);
5025+ };
5026+
5027+ auto makeContextItem = [&makeCallback](const winrt::hstring& label,
49925028 const winrt::hstring& icon,
4993- const auto & action) {
5029+ const winrt::hstring& tooltip,
5030+ const auto & action,
5031+ const auto & subMenu,
5032+ auto & targetMenu) {
49945033 AppBarButton button{};
49955034
49965035 if (!icon.empty ())
@@ -5002,34 +5041,122 @@ namespace winrt::TerminalApp::implementation
50025041
50035042 button.Label (label);
50045043 button.Click (makeCallback (action));
5005- menu.SecondaryCommands ().Append (button);
5044+ WUX::Controls::ToolTipService::SetToolTip (button, box_value (tooltip));
5045+ button.ContextFlyout (subMenu);
5046+ targetMenu.SecondaryCommands ().Append (button);
50065047 };
50075048
5049+ const auto focusedProfile = _GetFocusedTabImpl ()->GetFocusedProfile ();
5050+ auto separatorItem = AppBarSeparator{};
5051+ auto activeProfiles = _settings.ActiveProfiles ();
5052+ auto activeProfileCount = gsl::narrow_cast<int >(activeProfiles.Size ());
5053+ MUX::Controls::CommandBarFlyout splitPaneMenu{};
5054+
50085055 // Wire up each item to the action that should be performed. By actually
50095056 // connecting these to actions, we ensure the implementation is
50105057 // consistent. This also leaves room for customizing this menu with
50115058 // actions in the future.
50125059
5013- makeItem (RS_ (L" SplitPaneText" ), L" \xF246 " , ActionAndArgs{ ShortcutAction::SplitPane, SplitPaneArgs{ SplitType::Duplicate } });
5014- makeItem (RS_ (L" DuplicateTabText" ), L" \xF5ED " , ActionAndArgs{ ShortcutAction::DuplicateTab, nullptr });
5060+ makeItem (RS_ (L" DuplicateTabText" ), L" \xF5ED " , ActionAndArgs{ ShortcutAction::DuplicateTab, nullptr }, menu);
5061+
5062+ const auto focusedProfileName = focusedProfile.Name ();
5063+ const auto focusedProfileIcon = focusedProfile.Icon ();
5064+ const auto splitPaneDuplicateText = RS_ (L" SplitPaneDuplicateText" ) + L" " + focusedProfileName; // SplitPaneDuplicateText
5065+
5066+ const auto splitPaneRightText = RS_ (L" SplitPaneRightText" );
5067+ const auto splitPaneDownText = RS_ (L" SplitPaneDownText" );
5068+ const auto splitPaneUpText = RS_ (L" SplitPaneUpText" );
5069+ const auto splitPaneLeftText = RS_ (L" SplitPaneLeftText" );
5070+ const auto splitPaneToolTipText = RS_ (L" SplitPaneToolTipText" );
5071+
5072+ MUX::Controls::CommandBarFlyout splitPaneContextMenu{};
5073+ makeItem (splitPaneRightText, focusedProfileIcon, ActionAndArgs{ ShortcutAction::SplitPane, SplitPaneArgs{ SplitType::Duplicate, SplitDirection::Right, .5 , nullptr } }, splitPaneContextMenu);
5074+ makeItem (splitPaneDownText, focusedProfileIcon, ActionAndArgs{ ShortcutAction::SplitPane, SplitPaneArgs{ SplitType::Duplicate, SplitDirection::Down, .5 , nullptr } }, splitPaneContextMenu);
5075+ makeItem (splitPaneUpText, focusedProfileIcon, ActionAndArgs{ ShortcutAction::SplitPane, SplitPaneArgs{ SplitType::Duplicate, SplitDirection::Up, .5 , nullptr } }, splitPaneContextMenu);
5076+ makeItem (splitPaneLeftText, focusedProfileIcon, ActionAndArgs{ ShortcutAction::SplitPane, SplitPaneArgs{ SplitType::Duplicate, SplitDirection::Left, .5 , nullptr } }, splitPaneContextMenu);
5077+
5078+ makeContextItem (splitPaneDuplicateText, focusedProfileIcon, splitPaneToolTipText, ActionAndArgs{ ShortcutAction::SplitPane, SplitPaneArgs{ SplitType::Duplicate, SplitDirection::Automatic, .5 , nullptr } }, splitPaneContextMenu, splitPaneMenu);
5079+
5080+ // add menu separator
5081+ const auto separatorAutoItem = AppBarSeparator{};
5082+
5083+ splitPaneMenu.SecondaryCommands ().Append (separatorAutoItem);
5084+
5085+ for (auto profileIndex = 0 ; profileIndex < activeProfileCount; profileIndex++)
5086+ {
5087+ const auto profile = activeProfiles.GetAt (profileIndex);
5088+ const auto profileName = profile.Name ();
5089+ const auto profileIcon = profile.Icon ();
5090+
5091+ NewTerminalArgs args{};
5092+ args.Profile (profileName);
5093+
5094+ MUX::Controls::CommandBarFlyout splitPaneContextMenu{};
5095+ makeItem (splitPaneRightText, profileIcon, ActionAndArgs{ ShortcutAction::SplitPane, SplitPaneArgs{ SplitType::Manual, SplitDirection::Right, .5 , args } }, splitPaneContextMenu);
5096+ makeItem (splitPaneDownText, profileIcon, ActionAndArgs{ ShortcutAction::SplitPane, SplitPaneArgs{ SplitType::Manual, SplitDirection::Down, .5 , args } }, splitPaneContextMenu);
5097+ makeItem (splitPaneUpText, profileIcon, ActionAndArgs{ ShortcutAction::SplitPane, SplitPaneArgs{ SplitType::Manual, SplitDirection::Up, .5 , args } }, splitPaneContextMenu);
5098+ makeItem (splitPaneLeftText, profileIcon, ActionAndArgs{ ShortcutAction::SplitPane, SplitPaneArgs{ SplitType::Manual, SplitDirection::Left, .5 , args } }, splitPaneContextMenu);
5099+
5100+ makeContextItem (profileName, profileIcon, splitPaneToolTipText, ActionAndArgs{ ShortcutAction::SplitPane, SplitPaneArgs{ SplitType::Manual, SplitDirection::Automatic, .5 , args } }, splitPaneContextMenu, splitPaneMenu);
5101+ }
5102+
5103+ makeMenuItem (RS_ (L" SplitPaneText" ), L" \xF246 " , splitPaneMenu, menu);
50155104
50165105 // Only wire up "Close Pane" if there's multiple panes.
50175106 if (_GetFocusedTabImpl ()->GetLeafPaneCount () > 1 )
50185107 {
5019- makeItem (RS_ (L" PaneClose" ), L" \xE89F " , ActionAndArgs{ ShortcutAction::ClosePane, nullptr });
5108+ MUX::Controls::CommandBarFlyout swapPaneMenu{};
5109+ const auto rootPane = _GetFocusedTabImpl ()->GetRootPane ();
5110+ const auto mruPanes = _GetFocusedTabImpl ()->GetMruPanes ();
5111+ auto activePane = _GetFocusedTabImpl ()->GetActivePane ();
5112+ rootPane->WalkTree ([&](auto p) {
5113+ if (const auto & c{ p->GetTerminalControl () })
5114+ {
5115+ if (c == control)
5116+ {
5117+ activePane = p;
5118+ }
5119+ }
5120+ });
5121+
5122+ if (auto neighbor = rootPane->NavigateDirection (activePane, FocusDirection::Down, mruPanes))
5123+ {
5124+ makeItem (RS_ (L" SwapPaneDownText" ), neighbor->GetProfile ().Icon (), ActionAndArgs{ ShortcutAction::SwapPane, SwapPaneArgs{ FocusDirection::Down } }, swapPaneMenu);
5125+ }
5126+
5127+ if (auto neighbor = rootPane->NavigateDirection (activePane, FocusDirection::Right, mruPanes))
5128+ {
5129+ makeItem (RS_ (L" SwapPaneRightText" ), neighbor->GetProfile ().Icon (), ActionAndArgs{ ShortcutAction::SwapPane, SwapPaneArgs{ FocusDirection::Right } }, swapPaneMenu);
5130+ }
5131+
5132+ if (auto neighbor = rootPane->NavigateDirection (activePane, FocusDirection::Up, mruPanes))
5133+ {
5134+ makeItem (RS_ (L" SwapPaneUpText" ), neighbor->GetProfile ().Icon (), ActionAndArgs{ ShortcutAction::SwapPane, SwapPaneArgs{ FocusDirection::Up } }, swapPaneMenu);
5135+ }
5136+
5137+ if (auto neighbor = rootPane->NavigateDirection (activePane, FocusDirection::Left, mruPanes))
5138+ {
5139+ makeItem (RS_ (L" SwapPaneLeftText" ), neighbor->GetProfile ().Icon (), ActionAndArgs{ ShortcutAction::SwapPane, SwapPaneArgs{ FocusDirection::Left } }, swapPaneMenu);
5140+ }
5141+
5142+ makeMenuItem (RS_ (L" SwapPaneText" ), L" \xF1CB " , swapPaneMenu, menu);
5143+
5144+ makeItem (RS_ (L" TogglePaneZoomText" ), L" \xE8A3 " , ActionAndArgs{ ShortcutAction::TogglePaneZoom, nullptr }, menu);
5145+ makeItem (RS_ (L" CloseOtherPanesText" ), L" \xE89F " , ActionAndArgs{ ShortcutAction::CloseOtherPanes, nullptr }, menu);
5146+ makeItem (RS_ (L" PaneClose" ), L" \xE89F " , ActionAndArgs{ ShortcutAction::ClosePane, nullptr }, menu);
50205147 }
50215148
50225149 if (control.ConnectionState () >= ConnectionState::Closed)
50235150 {
5024- makeItem (RS_ (L" RestartConnectionText" ), L" \xE72C " , ActionAndArgs{ ShortcutAction::RestartConnection, nullptr });
5151+ makeItem (RS_ (L" RestartConnectionText" ), L" \xE72C " , ActionAndArgs{ ShortcutAction::RestartConnection, nullptr }, menu );
50255152 }
50265153
50275154 if (withSelection)
50285155 {
5029- makeItem (RS_ (L" SearchWebText" ), L" \xF6FA " , ActionAndArgs{ ShortcutAction::SearchForText, nullptr });
5156+ makeItem (RS_ (L" SearchWebText" ), L" \xF6FA " , ActionAndArgs{ ShortcutAction::SearchForText, nullptr }, menu );
50305157 }
50315158
5032- makeItem (RS_ (L" TabClose" ), L" \xE711 " , ActionAndArgs{ ShortcutAction::CloseTab, CloseTabArgs{ _GetFocusedTabIndex ().value () } });
5159+ makeItem (RS_ (L" TabClose" ), L" \xE711 " , ActionAndArgs{ ShortcutAction::CloseTab, CloseTabArgs{ _GetFocusedTabIndex ().value () } }, menu );
50335160 }
50345161
50355162 void TerminalPage::_PopulateQuickFixMenu (const TermControl& control,
0 commit comments