Skip to content

Commit

Permalink
Add action for closing all unfocused panes
Browse files Browse the repository at this point in the history
  • Loading branch information
JerBast committed Jul 20, 2022
1 parent 67662e1 commit 11bba27
Show file tree
Hide file tree
Showing 8 changed files with 170 additions and 114 deletions.
1 change: 1 addition & 0 deletions doc/cascadia/profiles.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,7 @@
"enum": [
"adjustFontSize",
"clearBuffer",
"closeOtherPanes",
"closeOtherTabs",
"closePane",
"closeTab",
Expand Down
7 changes: 7 additions & 0 deletions src/cascadia/TerminalApp/AppActionHandlers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,13 @@ namespace winrt::TerminalApp::implementation
}
}

void TerminalPage::_HandleCloseOtherPanes(const IInspectable& /*sender*/,
const ActionEventArgs& args)
{
_CloseUnfocusedPanes();
args.Handled(true);
}

void TerminalPage::_HandleMovePane(const IInspectable& /*sender*/,
const ActionEventArgs& args)
{
Expand Down
119 changes: 79 additions & 40 deletions src/cascadia/TerminalApp/TabManagement.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -760,6 +760,53 @@ namespace winrt::TerminalApp::implementation
}
}

// Method Description:
// - Removes the pane from the tab it belongs to.
// Arguments:
// - pane: the pane to close
// - detach: option to detach before closing the pane
winrt::Windows::Foundation::IAsyncAction TerminalPage::_HandleClosePaneRequested(std::shared_ptr<Pane> pane, bool detach)
{
if (const auto control{ pane->GetTerminalControl() })
{
if (control.ReadOnly())
{
auto warningResult = co_await _ShowCloseReadOnlyDialog();

// If the user didn't explicitly click on close tab - leave
if (warningResult != ContentDialogResult::Primary)
{
co_return;
}
control.ToggleReadOnly();
}
}

// Build the list of actions to recreate the closed pane,
// BuildStartupActions returns the "first" pane and the rest of
// its actions are assuming that first pane has been created first.
// This doesn't handle refocusing anything in particular, the
// result will be that the last pane created is focused. In the
// case of a single pane that is the desired behavior anyways.
auto state = pane->BuildStartupActions(0, 1);
{
ActionAndArgs splitPaneAction{};
splitPaneAction.Action(ShortcutAction::SplitPane);
SplitPaneArgs splitPaneArgs{ SplitDirection::Automatic, state.firstPane->GetTerminalArgsForPane() };
splitPaneAction.Args(splitPaneArgs);

state.args.emplace(state.args.begin(), std::move(splitPaneAction));
}
_AddPreviouslyClosedPaneOrTab(std::move(state.args));

// If specified, detach before closing to directly update the pane structure
if (detach)
{
_GetFocusedTabImpl()->GetRootPane()->DetachPane(pane);
}
pane->Close();
}

// Method Description:
// - Close the currently focused pane. If the pane is the last pane in the
// tab, the tab will also be closed. This will happen when we handle the
Expand All @@ -772,46 +819,7 @@ namespace winrt::TerminalApp::implementation

if (const auto pane{ terminalTab->GetActivePane() })
{
if (pane->ContainsReadOnly())
{
auto warningResult = co_await _ShowCloseReadOnlyDialog();

// If the user didn't explicitly click on close tab - leave
if (warningResult != ContentDialogResult::Primary)
{
co_return;
}

// Clean read-only mode to prevent additional prompt if closing the pane triggers closing of a hosting tab
pane->WalkTree([](auto p) {
if (const auto control{ p->GetTerminalControl() })
{
if (control.ReadOnly())
{
control.ToggleReadOnly();
}
}
});
}

// Build the list of actions to recreate the closed pane,
// BuildStartupActions returns the "first" pane and the rest of
// its actions are assuming that first pane has been created first.
// This doesn't handle refocusing anything in particular, the
// result will be that the last pane created is focused. In the
// case of a single pane that is the desired behavior anyways.
auto state = pane->BuildStartupActions(0, 1);
{
ActionAndArgs splitPaneAction{};
splitPaneAction.Action(ShortcutAction::SplitPane);
SplitPaneArgs splitPaneArgs{ SplitDirection::Automatic, state.firstPane->GetTerminalArgsForPane() };
splitPaneAction.Args(splitPaneArgs);

state.args.emplace(state.args.begin(), std::move(splitPaneAction));
}
_AddPreviouslyClosedPaneOrTab(std::move(state.args));

pane->Close();
co_await _HandleClosePaneRequested(pane, false);
}
}
else if (auto index{ _GetFocusedTabIndex() })
Expand All @@ -824,6 +832,37 @@ namespace winrt::TerminalApp::implementation
}
}

// Method Description:
// - Close all other panes except the pane that is currently focused.
winrt::fire_and_forget TerminalPage::_CloseUnfocusedPanes()
{
if (const auto terminalTab{ _GetFocusedTabImpl() })
{
const auto activePane = terminalTab->GetActivePane();
if (terminalTab->GetRootPane() != activePane)
{
// Accumulate list of all unfocused leaf panes
std::vector<uint32_t> unfocusedPaneIds{};
terminalTab->GetRootPane()->WalkTree([&](auto p) {
const auto id = p->Id();
if (id.has_value() && id != activePane->Id())
{
unfocusedPaneIds.push_back(id.value());
}
});

// Close all unfocused panes one by one
for (const auto unfocusedPaneId : unfocusedPaneIds)
{
if (const auto pane{ terminalTab->GetRootPane()->FindPane(unfocusedPaneId) })
{
co_await _HandleClosePaneRequested(pane, true);
}
}
}
}
}

// Method Description:
// - Close the tab at the given index.
void TerminalPage::_CloseTabAtIndex(uint32_t index)
Expand Down
2 changes: 2 additions & 0 deletions src/cascadia/TerminalApp/TerminalPage.h
Original file line number Diff line number Diff line change
Expand Up @@ -321,8 +321,10 @@ namespace winrt::TerminalApp::implementation
winrt::com_ptr<TerminalTab> _GetFocusedTabImpl() const noexcept;
TerminalApp::TabBase _GetTabByTabViewItem(const Microsoft::UI::Xaml::Controls::TabViewItem& tabViewItem) const noexcept;

winrt::Windows::Foundation::IAsyncAction _HandleClosePaneRequested(std::shared_ptr<Pane> pane, bool detach);
winrt::fire_and_forget _SetFocusedTab(const winrt::TerminalApp::TabBase tab);
winrt::fire_and_forget _CloseFocusedPane();
winrt::fire_and_forget _CloseUnfocusedPanes();
void _AddPreviouslyClosedPaneOrTab(std::vector<Microsoft::Terminal::Settings::Model::ActionAndArgs>&& args);

winrt::fire_and_forget _RemoveOnCloseRoutine(Microsoft::UI::Xaml::Controls::TabViewItem tabViewItem, winrt::com_ptr<TerminalPage> page);
Expand Down
2 changes: 2 additions & 0 deletions src/cascadia/TerminalSettingsModel/ActionAndArgs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include <LibraryResources.h>

static constexpr std::string_view AdjustFontSizeKey{ "adjustFontSize" };
static constexpr std::string_view CloseOtherPanesKey{ "closeOtherPanes" };
static constexpr std::string_view CloseOtherTabsKey{ "closeOtherTabs" };
static constexpr std::string_view ClosePaneKey{ "closePane" };
static constexpr std::string_view CloseTabKey{ "closeTab" };
Expand Down Expand Up @@ -329,6 +330,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
static const auto GeneratedActionNames = []() {
return std::unordered_map<ShortcutAction, winrt::hstring>{
{ ShortcutAction::AdjustFontSize, RS_(L"AdjustFontSizeCommandKey") },
{ ShortcutAction::CloseOtherPanes, RS_(L"CloseOtherPanesCommandKey") },
{ ShortcutAction::CloseOtherTabs, L"" }, // Intentionally omitted, must be generated by GenerateName
{ ShortcutAction::ClosePane, RS_(L"ClosePaneCommandKey") },
{ ShortcutAction::CloseTab, L"" }, // Intentionally omitted, must be generated by GenerateName
Expand Down
149 changes: 75 additions & 74 deletions src/cascadia/TerminalSettingsModel/AllShortcutActions.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,80 +23,81 @@
// each action. This is _NOT_ something that should be used when any individual
// case should be customized.

#define ALL_SHORTCUT_ACTIONS \
ON_ALL_ACTIONS(CopyText) \
ON_ALL_ACTIONS(PasteText) \
ON_ALL_ACTIONS(OpenNewTabDropdown) \
ON_ALL_ACTIONS(DuplicateTab) \
ON_ALL_ACTIONS(NewTab) \
ON_ALL_ACTIONS(CloseWindow) \
ON_ALL_ACTIONS(CloseTab) \
ON_ALL_ACTIONS(ClosePane) \
ON_ALL_ACTIONS(NextTab) \
ON_ALL_ACTIONS(PrevTab) \
ON_ALL_ACTIONS(SendInput) \
ON_ALL_ACTIONS(SplitPane) \
ON_ALL_ACTIONS(ToggleSplitOrientation) \
ON_ALL_ACTIONS(TogglePaneZoom) \
ON_ALL_ACTIONS(SwitchToTab) \
ON_ALL_ACTIONS(AdjustFontSize) \
ON_ALL_ACTIONS(ResetFontSize) \
ON_ALL_ACTIONS(ScrollUp) \
ON_ALL_ACTIONS(ScrollDown) \
ON_ALL_ACTIONS(ScrollUpPage) \
ON_ALL_ACTIONS(ScrollDownPage) \
ON_ALL_ACTIONS(ScrollToTop) \
ON_ALL_ACTIONS(ScrollToBottom) \
ON_ALL_ACTIONS(ScrollToMark) \
ON_ALL_ACTIONS(AddMark) \
ON_ALL_ACTIONS(ClearMark) \
ON_ALL_ACTIONS(ClearAllMarks) \
ON_ALL_ACTIONS(ResizePane) \
ON_ALL_ACTIONS(MoveFocus) \
ON_ALL_ACTIONS(MovePane) \
ON_ALL_ACTIONS(SwapPane) \
ON_ALL_ACTIONS(Find) \
ON_ALL_ACTIONS(ToggleShaderEffects) \
ON_ALL_ACTIONS(ToggleFocusMode) \
ON_ALL_ACTIONS(ToggleFullscreen) \
ON_ALL_ACTIONS(ToggleAlwaysOnTop) \
ON_ALL_ACTIONS(OpenSettings) \
ON_ALL_ACTIONS(SetFocusMode) \
ON_ALL_ACTIONS(SetFullScreen) \
ON_ALL_ACTIONS(SetMaximized) \
ON_ALL_ACTIONS(SetColorScheme) \
ON_ALL_ACTIONS(SetTabColor) \
ON_ALL_ACTIONS(OpenTabColorPicker) \
ON_ALL_ACTIONS(RenameTab) \
ON_ALL_ACTIONS(OpenTabRenamer) \
ON_ALL_ACTIONS(ExecuteCommandline) \
ON_ALL_ACTIONS(ToggleCommandPalette) \
ON_ALL_ACTIONS(CloseOtherTabs) \
ON_ALL_ACTIONS(CloseTabsAfter) \
ON_ALL_ACTIONS(TabSearch) \
ON_ALL_ACTIONS(MoveTab) \
ON_ALL_ACTIONS(BreakIntoDebugger) \
ON_ALL_ACTIONS(TogglePaneReadOnly) \
ON_ALL_ACTIONS(FindMatch) \
ON_ALL_ACTIONS(NewWindow) \
ON_ALL_ACTIONS(IdentifyWindow) \
ON_ALL_ACTIONS(IdentifyWindows) \
ON_ALL_ACTIONS(RenameWindow) \
ON_ALL_ACTIONS(OpenWindowRenamer) \
ON_ALL_ACTIONS(GlobalSummon) \
ON_ALL_ACTIONS(QuakeMode) \
ON_ALL_ACTIONS(FocusPane) \
ON_ALL_ACTIONS(OpenSystemMenu) \
ON_ALL_ACTIONS(ExportBuffer) \
ON_ALL_ACTIONS(ClearBuffer) \
ON_ALL_ACTIONS(MultipleActions) \
ON_ALL_ACTIONS(Quit) \
ON_ALL_ACTIONS(AdjustOpacity) \
ON_ALL_ACTIONS(RestoreLastClosed) \
ON_ALL_ACTIONS(SelectAll) \
ON_ALL_ACTIONS(MarkMode) \
ON_ALL_ACTIONS(ToggleBlockSelection) \
ON_ALL_ACTIONS(SwitchSelectionEndpoint)
#define ALL_SHORTCUT_ACTIONS \
ON_ALL_ACTIONS(CopyText) \
ON_ALL_ACTIONS(PasteText) \
ON_ALL_ACTIONS(OpenNewTabDropdown) \
ON_ALL_ACTIONS(DuplicateTab) \
ON_ALL_ACTIONS(NewTab) \
ON_ALL_ACTIONS(CloseWindow) \
ON_ALL_ACTIONS(CloseTab) \
ON_ALL_ACTIONS(ClosePane) \
ON_ALL_ACTIONS(NextTab) \
ON_ALL_ACTIONS(PrevTab) \
ON_ALL_ACTIONS(SendInput) \
ON_ALL_ACTIONS(SplitPane) \
ON_ALL_ACTIONS(ToggleSplitOrientation) \
ON_ALL_ACTIONS(TogglePaneZoom) \
ON_ALL_ACTIONS(SwitchToTab) \
ON_ALL_ACTIONS(AdjustFontSize) \
ON_ALL_ACTIONS(ResetFontSize) \
ON_ALL_ACTIONS(ScrollUp) \
ON_ALL_ACTIONS(ScrollDown) \
ON_ALL_ACTIONS(ScrollUpPage) \
ON_ALL_ACTIONS(ScrollDownPage) \
ON_ALL_ACTIONS(ScrollToTop) \
ON_ALL_ACTIONS(ScrollToBottom) \
ON_ALL_ACTIONS(ScrollToMark) \
ON_ALL_ACTIONS(AddMark) \
ON_ALL_ACTIONS(ClearMark) \
ON_ALL_ACTIONS(ClearAllMarks) \
ON_ALL_ACTIONS(ResizePane) \
ON_ALL_ACTIONS(MoveFocus) \
ON_ALL_ACTIONS(MovePane) \
ON_ALL_ACTIONS(SwapPane) \
ON_ALL_ACTIONS(Find) \
ON_ALL_ACTIONS(ToggleShaderEffects) \
ON_ALL_ACTIONS(ToggleFocusMode) \
ON_ALL_ACTIONS(ToggleFullscreen) \
ON_ALL_ACTIONS(ToggleAlwaysOnTop) \
ON_ALL_ACTIONS(OpenSettings) \
ON_ALL_ACTIONS(SetFocusMode) \
ON_ALL_ACTIONS(SetFullScreen) \
ON_ALL_ACTIONS(SetMaximized) \
ON_ALL_ACTIONS(SetColorScheme) \
ON_ALL_ACTIONS(SetTabColor) \
ON_ALL_ACTIONS(OpenTabColorPicker) \
ON_ALL_ACTIONS(RenameTab) \
ON_ALL_ACTIONS(OpenTabRenamer) \
ON_ALL_ACTIONS(ExecuteCommandline) \
ON_ALL_ACTIONS(ToggleCommandPalette) \
ON_ALL_ACTIONS(CloseOtherTabs) \
ON_ALL_ACTIONS(CloseTabsAfter) \
ON_ALL_ACTIONS(TabSearch) \
ON_ALL_ACTIONS(MoveTab) \
ON_ALL_ACTIONS(BreakIntoDebugger) \
ON_ALL_ACTIONS(TogglePaneReadOnly) \
ON_ALL_ACTIONS(FindMatch) \
ON_ALL_ACTIONS(NewWindow) \
ON_ALL_ACTIONS(IdentifyWindow) \
ON_ALL_ACTIONS(IdentifyWindows) \
ON_ALL_ACTIONS(RenameWindow) \
ON_ALL_ACTIONS(OpenWindowRenamer) \
ON_ALL_ACTIONS(GlobalSummon) \
ON_ALL_ACTIONS(QuakeMode) \
ON_ALL_ACTIONS(FocusPane) \
ON_ALL_ACTIONS(OpenSystemMenu) \
ON_ALL_ACTIONS(ExportBuffer) \
ON_ALL_ACTIONS(ClearBuffer) \
ON_ALL_ACTIONS(MultipleActions) \
ON_ALL_ACTIONS(Quit) \
ON_ALL_ACTIONS(AdjustOpacity) \
ON_ALL_ACTIONS(RestoreLastClosed) \
ON_ALL_ACTIONS(SelectAll) \
ON_ALL_ACTIONS(MarkMode) \
ON_ALL_ACTIONS(ToggleBlockSelection) \
ON_ALL_ACTIONS(SwitchSelectionEndpoint) \
ON_ALL_ACTIONS(CloseOtherPanes)

#define ALL_SHORTCUT_ACTIONS_WITH_ARGS \
ON_ALL_ACTIONS_WITH_ARGS(AdjustFontSize) \
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -567,4 +567,7 @@
<data name="SwitchSelectionEndpointCommandKey" xml:space="preserve">
<value>Switch selection endpoint</value>
</data>
<data name="CloseOtherPanesCommandKey" xml:space="preserve">
<value>Close all other panes</value>
</data>
</root>
1 change: 1 addition & 0 deletions src/cascadia/TerminalSettingsModel/defaults.json
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,7 @@
{ "command": { "action": "switchToTab", "index": 4294967295 }, "keys": "ctrl+alt+9" },

// Pane Management
{ "command": "closeOtherPanes" },
{ "command": "closePane", "keys": "ctrl+shift+w" },
{ "command": { "action": "splitPane", "split": "up" } },
{ "command": { "action": "splitPane", "split": "down" }, "keys": "alt+shift+-" },
Expand Down

0 comments on commit 11bba27

Please sign in to comment.