diff --git a/src/cascadia/TerminalApp/AppActionHandlers.cpp b/src/cascadia/TerminalApp/AppActionHandlers.cpp index 8b2cd7b3637..ae0e8429033 100644 --- a/src/cascadia/TerminalApp/AppActionHandlers.cpp +++ b/src/cascadia/TerminalApp/AppActionHandlers.cpp @@ -285,6 +285,28 @@ namespace winrt::TerminalApp::implementation args.Handled(true); } + void TerminalPage::_HandleEnablePaneReadOnly(const IInspectable& /*sender*/, + const ActionEventArgs& args) + { + if (const auto activeTab{ _GetFocusedTabImpl() }) + { + activeTab->SetPaneReadOnly(true); + } + + args.Handled(true); + } + + void TerminalPage::_HandleDisablePaneReadOnly(const IInspectable& /*sender*/, + const ActionEventArgs& args) + { + if (const auto activeTab{ _GetFocusedTabImpl() }) + { + activeTab->SetPaneReadOnly(false); + } + + args.Handled(true); + } + void TerminalPage::_HandleScrollUpPage(const IInspectable& /*sender*/, const ActionEventArgs& args) { diff --git a/src/cascadia/TerminalApp/TerminalTab.cpp b/src/cascadia/TerminalApp/TerminalTab.cpp index 8cd4ae86acd..b6d961d2c5b 100644 --- a/src/cascadia/TerminalApp/TerminalTab.cpp +++ b/src/cascadia/TerminalApp/TerminalTab.cpp @@ -1563,14 +1563,14 @@ namespace winrt::TerminalApp::implementation { auto hasReadOnly = false; auto allReadOnly = true; - _activePane->WalkTree([&](auto p) { + _activePane->WalkTree([&](const auto& p) { if (const auto& control{ p->GetTerminalControl() }) { hasReadOnly |= control.ReadOnly(); allReadOnly &= control.ReadOnly(); } }); - _activePane->WalkTree([&](auto p) { + _activePane->WalkTree([&](const auto& p) { if (const auto& control{ p->GetTerminalControl() }) { // If all controls have the same read only state then just toggle @@ -1587,6 +1587,38 @@ namespace winrt::TerminalApp::implementation }); } + // Method Description: + // - Set read-only mode on the active pane + // - If a parent pane is selected, this will ensure that all children have + // the same read-only status. + void TerminalTab::SetPaneReadOnly(const bool readOnlyState) + { + auto hasReadOnly = false; + auto allReadOnly = true; + _activePane->WalkTree([&](const auto& p) { + if (const auto& control{ p->GetTerminalControl() }) + { + hasReadOnly |= control.ReadOnly(); + allReadOnly &= control.ReadOnly(); + } + }); + _activePane->WalkTree([&](const auto& p) { + if (const auto& control{ p->GetTerminalControl() }) + { + // If all controls have the same read only state then just disable + if (allReadOnly || !hasReadOnly) + { + control.SetReadOnly(readOnlyState); + } + // otherwise set to all read only. + else if (!control.ReadOnly()) + { + control.SetReadOnly(readOnlyState); + } + } + }); + } + // Method Description: // - Calculates if the tab is read-only. // The tab is considered read-only if one of the panes is read-only. diff --git a/src/cascadia/TerminalApp/TerminalTab.h b/src/cascadia/TerminalApp/TerminalTab.h index 53492095db1..f607563e188 100644 --- a/src/cascadia/TerminalApp/TerminalTab.h +++ b/src/cascadia/TerminalApp/TerminalTab.h @@ -87,6 +87,8 @@ namespace winrt::TerminalApp::implementation int GetLeafPaneCount() const noexcept; void TogglePaneReadOnly(); + void SetPaneReadOnly(const bool readOnlyState); + std::shared_ptr GetActivePane() const; winrt::TerminalApp::TaskbarState GetCombinedTaskbarState() const; diff --git a/src/cascadia/TerminalControl/ControlCore.cpp b/src/cascadia/TerminalControl/ControlCore.cpp index 1e7829940d1..2f3d4e44a86 100644 --- a/src/cascadia/TerminalControl/ControlCore.cpp +++ b/src/cascadia/TerminalControl/ControlCore.cpp @@ -1671,6 +1671,11 @@ namespace winrt::Microsoft::Terminal::Control::implementation _isReadOnly = !_isReadOnly; } + void ControlCore::SetReadOnlyMode(const bool readOnlyState) + { + _isReadOnly = readOnlyState; + } + void ControlCore::_raiseReadOnlyWarning() { auto noticeArgs = winrt::make(NoticeLevel::Info, RS_(L"TermControlReadOnly")); diff --git a/src/cascadia/TerminalControl/ControlCore.h b/src/cascadia/TerminalControl/ControlCore.h index f9c7792f6ae..10582981d34 100644 --- a/src/cascadia/TerminalControl/ControlCore.h +++ b/src/cascadia/TerminalControl/ControlCore.h @@ -193,6 +193,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation bool IsInReadOnlyMode() const; void ToggleReadOnlyMode(); + void SetReadOnlyMode(const bool readOnlyState); hstring ReadEntireBuffer() const; diff --git a/src/cascadia/TerminalControl/ControlCore.idl b/src/cascadia/TerminalControl/ControlCore.idl index a8df501469b..e62f4f35adc 100644 --- a/src/cascadia/TerminalControl/ControlCore.idl +++ b/src/cascadia/TerminalControl/ControlCore.idl @@ -111,6 +111,7 @@ namespace Microsoft.Terminal.Control void ToggleShaderEffects(); void ToggleReadOnlyMode(); + void SetReadOnlyMode(Boolean readOnlyState); Microsoft.Terminal.Core.Point CursorPosition { get; }; void ResumeRendering(); diff --git a/src/cascadia/TerminalControl/TermControl.cpp b/src/cascadia/TerminalControl/TermControl.cpp index 40081c30b62..11114910660 100644 --- a/src/cascadia/TerminalControl/TermControl.cpp +++ b/src/cascadia/TerminalControl/TermControl.cpp @@ -2925,6 +2925,14 @@ namespace winrt::Microsoft::Terminal::Control::implementation _ReadOnlyChangedHandlers(*this, winrt::box_value(_core.IsInReadOnlyMode())); } + // Method Description: + // - Sets the read-only flag, raises event describing the value change + void TermControl::SetReadOnly(const bool readOnlyState) + { + _core.SetReadOnlyMode(readOnlyState); + _ReadOnlyChangedHandlers(*this, winrt::box_value(_core.IsInReadOnlyMode())); + } + // Method Description: // - Handle a mouse exited event, specifically clearing last hovered cell // and removing selection from hyper link if exists diff --git a/src/cascadia/TerminalControl/TermControl.h b/src/cascadia/TerminalControl/TermControl.h index e8f0bb8734d..2dc5377b679 100644 --- a/src/cascadia/TerminalControl/TermControl.h +++ b/src/cascadia/TerminalControl/TermControl.h @@ -124,6 +124,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation bool ReadOnly() const noexcept; void ToggleReadOnly(); + void SetReadOnly(const bool readOnlyState); static Control::MouseButtonState GetPressedMouseButtons(const winrt::Windows::UI::Input::PointerPoint point); static unsigned int GetPointerUpdateKind(const winrt::Windows::UI::Input::PointerPoint point); diff --git a/src/cascadia/TerminalControl/TermControl.idl b/src/cascadia/TerminalControl/TermControl.idl index 3c9f794f42c..b2fd88d0bbb 100644 --- a/src/cascadia/TerminalControl/TermControl.idl +++ b/src/cascadia/TerminalControl/TermControl.idl @@ -89,6 +89,7 @@ namespace Microsoft.Terminal.Control Boolean ReadOnly { get; }; void ToggleReadOnly(); + void SetReadOnly(Boolean readOnlyState); String ReadEntireBuffer(); diff --git a/src/cascadia/TerminalSettingsModel/ActionAndArgs.cpp b/src/cascadia/TerminalSettingsModel/ActionAndArgs.cpp index 12ca43475d2..e43320f994d 100644 --- a/src/cascadia/TerminalSettingsModel/ActionAndArgs.cpp +++ b/src/cascadia/TerminalSettingsModel/ActionAndArgs.cpp @@ -65,6 +65,8 @@ static constexpr std::string_view MoveTabKey{ "moveTab" }; static constexpr std::string_view BreakIntoDebuggerKey{ "breakIntoDebugger" }; static constexpr std::string_view FindMatchKey{ "findMatch" }; static constexpr std::string_view TogglePaneReadOnlyKey{ "toggleReadOnlyMode" }; +static constexpr std::string_view EnablePaneReadOnlyKey{ "enableReadOnlyMode" }; +static constexpr std::string_view DisablePaneReadOnlyKey{ "disableReadOnlyMode" }; static constexpr std::string_view NewWindowKey{ "newWindow" }; static constexpr std::string_view IdentifyWindowKey{ "identifyWindow" }; static constexpr std::string_view IdentifyWindowsKey{ "identifyWindows" }; @@ -387,6 +389,8 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation { ShortcutAction::BreakIntoDebugger, RS_(L"BreakIntoDebuggerCommandKey") }, { ShortcutAction::FindMatch, L"" }, // Intentionally omitted, must be generated by GenerateName { ShortcutAction::TogglePaneReadOnly, RS_(L"TogglePaneReadOnlyCommandKey") }, + { ShortcutAction::EnablePaneReadOnly, RS_(L"EnablePaneReadOnlyCommandKey") }, + { ShortcutAction::DisablePaneReadOnly, RS_(L"DisablePaneReadOnlyCommandKey") }, { ShortcutAction::NewWindow, RS_(L"NewWindowCommandKey") }, { ShortcutAction::IdentifyWindow, RS_(L"IdentifyWindowCommandKey") }, { ShortcutAction::IdentifyWindows, RS_(L"IdentifyWindowsCommandKey") }, diff --git a/src/cascadia/TerminalSettingsModel/AllShortcutActions.h b/src/cascadia/TerminalSettingsModel/AllShortcutActions.h index efb861667c1..326409a7c23 100644 --- a/src/cascadia/TerminalSettingsModel/AllShortcutActions.h +++ b/src/cascadia/TerminalSettingsModel/AllShortcutActions.h @@ -77,6 +77,8 @@ ON_ALL_ACTIONS(MoveTab) \ ON_ALL_ACTIONS(BreakIntoDebugger) \ ON_ALL_ACTIONS(TogglePaneReadOnly) \ + ON_ALL_ACTIONS(EnablePaneReadOnly) \ + ON_ALL_ACTIONS(DisablePaneReadOnly) \ ON_ALL_ACTIONS(FindMatch) \ ON_ALL_ACTIONS(NewWindow) \ ON_ALL_ACTIONS(IdentifyWindow) \ diff --git a/src/cascadia/TerminalSettingsModel/Resources/en-US/Resources.resw b/src/cascadia/TerminalSettingsModel/Resources/en-US/Resources.resw index 09998b9093f..c79aea0a705 100644 --- a/src/cascadia/TerminalSettingsModel/Resources/en-US/Resources.resw +++ b/src/cascadia/TerminalSettingsModel/Resources/en-US/Resources.resw @@ -472,6 +472,12 @@ Toggle pane read-only mode + + Enable pane read-only mode + + + Disable pane read-only mode + Toggle terminal visual effects diff --git a/src/cascadia/TerminalSettingsModel/defaults.json b/src/cascadia/TerminalSettingsModel/defaults.json index 59a7f231c81..9d850dd1c9b 100644 --- a/src/cascadia/TerminalSettingsModel/defaults.json +++ b/src/cascadia/TerminalSettingsModel/defaults.json @@ -408,6 +408,8 @@ { "command": "togglePaneZoom" }, { "command": "toggleSplitOrientation" }, { "command": "toggleReadOnlyMode" }, + { "command": "enableReadOnlyMode" }, + { "command": "disableReadOnlyMode" }, { "command": { "action": "movePane", "index": 0 } }, { "command": { "action": "movePane", "index": 1 } }, { "command": { "action": "movePane", "index": 2 } },