diff --git a/src/cascadia/LocalTests_TerminalApp/SettingsTests.cpp b/src/cascadia/LocalTests_TerminalApp/SettingsTests.cpp index ba77341f9a..eff9e8d496 100644 --- a/src/cascadia/LocalTests_TerminalApp/SettingsTests.cpp +++ b/src/cascadia/LocalTests_TerminalApp/SettingsTests.cpp @@ -127,7 +127,7 @@ namespace TerminalAppLocalTests void SettingsTests::TryCreateWinRTType() { - winrt::Microsoft::Terminal::Settings::TerminalSettings settings; + TerminalSettings settings; VERIFY_IS_NOT_NULL(settings); auto oldFontSize = settings.FontSize(); settings.FontSize(oldFontSize + 5); diff --git a/src/cascadia/LocalTests_TerminalApp/TabTests.cpp b/src/cascadia/LocalTests_TerminalApp/TabTests.cpp index b515eacd93..3c417174c5 100644 --- a/src/cascadia/LocalTests_TerminalApp/TabTests.cpp +++ b/src/cascadia/LocalTests_TerminalApp/TabTests.cpp @@ -84,7 +84,7 @@ namespace TerminalAppLocalTests { // Verify we can create a WinRT type we authored // Just creating it is enough to know that everything is working. - winrt::Microsoft::Terminal::Settings::TerminalSettings settings; + TerminalSettings settings; VERIFY_IS_NOT_NULL(settings); auto oldFontSize = settings.FontSize(); settings.FontSize(oldFontSize + 5); @@ -140,7 +140,7 @@ namespace TerminalAppLocalTests // 4. one of our types that uses MUX/Xaml in this dll (Tab). // Just creating all of them is enough to know that everything is working. const auto profileGuid{ Utils::CreateGuid() }; - winrt::Microsoft::Terminal::Settings::TerminalSettings settings{}; + TerminalSettings settings{}; VERIFY_IS_NOT_NULL(settings); winrt::Microsoft::Terminal::TerminalConnection::EchoConnection conn{}; VERIFY_IS_NOT_NULL(conn); diff --git a/src/cascadia/PublicTerminalCore/HwndTerminal.cpp b/src/cascadia/PublicTerminalCore/HwndTerminal.cpp index 27775bb314..3c3e160019 100644 --- a/src/cascadia/PublicTerminalCore/HwndTerminal.cpp +++ b/src/cascadia/PublicTerminalCore/HwndTerminal.cpp @@ -55,10 +55,29 @@ try if (terminal) { - if (_IsMouseMessage(uMsg) && terminal->_CanSendVTMouseInput()) + if (_IsMouseMessage(uMsg)) { - if (terminal->_SendMouseEvent(uMsg, wParam, lParam)) + if (terminal->_CanSendVTMouseInput() && terminal->_SendMouseEvent(uMsg, wParam, lParam)) { + // GH#6401: Capturing the mouse ensures that we get drag/release events + // even if the user moves outside the window. + // _SendMouseEvent returns false if the terminal's not in VT mode, so we'll + // fall through to release the capture. + switch (uMsg) + { + case WM_LBUTTONDOWN: + case WM_MBUTTONDOWN: + case WM_RBUTTONDOWN: + SetCapture(hwnd); + break; + case WM_LBUTTONUP: + case WM_MBUTTONUP: + case WM_RBUTTONUP: + ReleaseCapture(); + break; + } + + // Suppress all mouse events that made it into the terminal. return 0; } } @@ -76,6 +95,10 @@ try return 0; case WM_LBUTTONUP: terminal->_singleClickTouchdownPos = std::nullopt; + [[fallthrough]]; + case WM_MBUTTONUP: + case WM_RBUTTONUP: + ReleaseCapture(); break; case WM_MOUSEMOVE: if (WI_IsFlagSet(wParam, MK_LBUTTON)) diff --git a/src/cascadia/TerminalApp/CascadiaSettings.h b/src/cascadia/TerminalApp/CascadiaSettings.h index 2172292066..b8d1b93763 100644 --- a/src/cascadia/TerminalApp/CascadiaSettings.h +++ b/src/cascadia/TerminalApp/CascadiaSettings.h @@ -54,8 +54,8 @@ public: static const CascadiaSettings& GetCurrentAppSettings(); - std::tuple BuildSettings(const winrt::TerminalApp::NewTerminalArgs& newTerminalArgs) const; - winrt::Microsoft::Terminal::Settings::TerminalSettings BuildSettings(GUID profileGuid) const; + std::tuple BuildSettings(const winrt::TerminalApp::NewTerminalArgs& newTerminalArgs) const; + winrt::TerminalApp::TerminalSettings BuildSettings(GUID profileGuid) const; GlobalAppSettings& GlobalSettings(); diff --git a/src/cascadia/TerminalApp/ColorScheme.cpp b/src/cascadia/TerminalApp/ColorScheme.cpp index 6627d2b745..b04090b6e0 100644 --- a/src/cascadia/TerminalApp/ColorScheme.cpp +++ b/src/cascadia/TerminalApp/ColorScheme.cpp @@ -10,7 +10,7 @@ using namespace ::Microsoft::Console; using namespace TerminalApp; -using namespace winrt::Microsoft::Terminal::Settings; +using namespace winrt::TerminalApp; static constexpr std::string_view NameKey{ "name" }; static constexpr std::string_view ForegroundKey{ "foreground" }; diff --git a/src/cascadia/TerminalApp/ColorScheme.h b/src/cascadia/TerminalApp/ColorScheme.h index 2fb007237b..4eafdc75b7 100644 --- a/src/cascadia/TerminalApp/ColorScheme.h +++ b/src/cascadia/TerminalApp/ColorScheme.h @@ -15,7 +15,7 @@ Author(s): --*/ #pragma once -#include +#include "TerminalSettings.h" #include "../../inc/conattrs.hpp" // fwdecl unittest classes @@ -37,7 +37,7 @@ public: ColorScheme(std::wstring name, til::color defaultFg, til::color defaultBg, til::color cursorColor); ~ColorScheme(); - void ApplyScheme(winrt::Microsoft::Terminal::Settings::TerminalSettings terminalSettings) const; + void ApplyScheme(winrt::TerminalApp::TerminalSettings terminalSettings) const; static ColorScheme FromJson(const Json::Value& json); bool ShouldBeLayered(const Json::Value& json) const; diff --git a/src/cascadia/TerminalApp/GlobalAppSettings.h b/src/cascadia/TerminalApp/GlobalAppSettings.h index d502eb5593..573872882d 100644 --- a/src/cascadia/TerminalApp/GlobalAppSettings.h +++ b/src/cascadia/TerminalApp/GlobalAppSettings.h @@ -46,7 +46,7 @@ public: static GlobalAppSettings FromJson(const Json::Value& json); void LayerJson(const Json::Value& json); - void ApplyToSettings(winrt::Microsoft::Terminal::Settings::TerminalSettings& settings) const noexcept; + void ApplyToSettings(winrt::TerminalApp::TerminalSettings& settings) const noexcept; std::vector GetKeybindingsWarnings() const; diff --git a/src/cascadia/TerminalApp/Pane.h b/src/cascadia/TerminalApp/Pane.h index a9c7bd9ceb..dfbcf1e7bc 100644 --- a/src/cascadia/TerminalApp/Pane.h +++ b/src/cascadia/TerminalApp/Pane.h @@ -51,7 +51,7 @@ public: void ClearActive(); void SetActive(); - void UpdateSettings(const winrt::Microsoft::Terminal::Settings::TerminalSettings& settings, + void UpdateSettings(const winrt::TerminalApp::TerminalSettings& settings, const GUID& profile); void ResizeContent(const winrt::Windows::Foundation::Size& newSize); void Relayout(); diff --git a/src/cascadia/TerminalApp/Profile.cpp b/src/cascadia/TerminalApp/Profile.cpp index 7cd80a65b1..b98efb9f69 100644 --- a/src/cascadia/TerminalApp/Profile.cpp +++ b/src/cascadia/TerminalApp/Profile.cpp @@ -12,6 +12,7 @@ #include "TerminalSettingsSerializationHelpers.h" using namespace TerminalApp; +using namespace winrt::TerminalApp; using namespace winrt::Microsoft::Terminal::Settings; using namespace winrt::Windows::UI::Xaml; using namespace ::Microsoft::Console; diff --git a/src/cascadia/TerminalApp/Profile.h b/src/cascadia/TerminalApp/Profile.h index 17edad98bb..1e145e669c 100644 --- a/src/cascadia/TerminalApp/Profile.h +++ b/src/cascadia/TerminalApp/Profile.h @@ -46,7 +46,7 @@ public: ~Profile(); - winrt::Microsoft::Terminal::Settings::TerminalSettings CreateTerminalSettings(const std::unordered_map& schemes) const; + winrt::TerminalApp::TerminalSettings CreateTerminalSettings(const std::unordered_map& schemes) const; Json::Value GenerateStub() const; static Profile FromJson(const Json::Value& json); diff --git a/src/cascadia/TerminalApp/Tab.h b/src/cascadia/TerminalApp/Tab.h index a6752fe6bb..055d631c42 100644 --- a/src/cascadia/TerminalApp/Tab.h +++ b/src/cascadia/TerminalApp/Tab.h @@ -46,7 +46,7 @@ namespace winrt::TerminalApp::implementation void ResizePane(const winrt::TerminalApp::Direction& direction); void NavigateFocus(const winrt::TerminalApp::Direction& direction); - void UpdateSettings(const winrt::Microsoft::Terminal::Settings::TerminalSettings& settings, const GUID& profile); + void UpdateSettings(const winrt::TerminalApp::TerminalSettings& settings, const GUID& profile); winrt::hstring GetActiveTitle() const; void Shutdown(); diff --git a/src/cascadia/TerminalApp/TerminalPage.cpp b/src/cascadia/TerminalApp/TerminalPage.cpp index 944b38cabd..22addec202 100644 --- a/src/cascadia/TerminalApp/TerminalPage.cpp +++ b/src/cascadia/TerminalApp/TerminalPage.cpp @@ -32,7 +32,6 @@ using namespace winrt::Windows::UI::Text; using namespace winrt::Microsoft::Terminal; using namespace winrt::Microsoft::Terminal::TerminalControl; using namespace winrt::Microsoft::Terminal::TerminalConnection; -using namespace winrt::Microsoft::Terminal::Settings; using namespace ::TerminalApp; using namespace ::Microsoft::Console; @@ -677,7 +676,7 @@ namespace winrt::TerminalApp::implementation // currently displayed, it will be shown. // Arguments: // - settings: the TerminalSettings object to use to create the TerminalControl with. - void TerminalPage::_CreateNewTabFromSettings(GUID profileGuid, TerminalSettings settings) + void TerminalPage::_CreateNewTabFromSettings(GUID profileGuid, TerminalApp::TerminalSettings settings) { // Initialize the new tab @@ -778,7 +777,7 @@ namespace winrt::TerminalApp::implementation // Return value: // - the desired connection TerminalConnection::ITerminalConnection TerminalPage::_CreateConnectionFromSettings(GUID profileGuid, - winrt::Microsoft::Terminal::Settings::TerminalSettings settings) + TerminalApp::TerminalSettings settings) { const auto* const profile = _settings->FindProfile(profileGuid); @@ -1419,7 +1418,7 @@ namespace winrt::TerminalApp::implementation try { auto focusedTab = _GetStrongTabImpl(*indexOpt); - winrt::Microsoft::Terminal::Settings::TerminalSettings controlSettings; + TerminalApp::TerminalSettings controlSettings; GUID realGuid; bool profileFound = false; diff --git a/src/cascadia/TerminalApp/TerminalPage.h b/src/cascadia/TerminalApp/TerminalPage.h index f78cfe86f2..021be7a3e1 100644 --- a/src/cascadia/TerminalApp/TerminalPage.h +++ b/src/cascadia/TerminalApp/TerminalPage.h @@ -118,8 +118,8 @@ namespace winrt::TerminalApp::implementation void _CreateNewTabFlyout(); void _OpenNewTabDropdown(); void _OpenNewTab(const winrt::TerminalApp::NewTerminalArgs& newTerminalArgs); - void _CreateNewTabFromSettings(GUID profileGuid, winrt::Microsoft::Terminal::Settings::TerminalSettings settings); - winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection _CreateConnectionFromSettings(GUID profileGuid, winrt::Microsoft::Terminal::Settings::TerminalSettings settings); + void _CreateNewTabFromSettings(GUID profileGuid, TerminalApp::TerminalSettings settings); + winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection _CreateConnectionFromSettings(GUID profileGuid, TerminalApp::TerminalSettings settings); void _SettingsButtonOnClick(const IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& eventArgs); void _FeedbackButtonOnClick(const IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& eventArgs); diff --git a/src/cascadia/TerminalSettings/TerminalSettings.cpp b/src/cascadia/TerminalApp/TerminalSettings.cpp similarity index 87% rename from src/cascadia/TerminalSettings/TerminalSettings.cpp rename to src/cascadia/TerminalApp/TerminalSettings.cpp index 02d8f452e8..3313736e65 100644 --- a/src/cascadia/TerminalSettings/TerminalSettings.cpp +++ b/src/cascadia/TerminalApp/TerminalSettings.cpp @@ -6,7 +6,7 @@ #include "TerminalSettings.g.cpp" -namespace winrt::Microsoft::Terminal::Settings::implementation +namespace winrt::TerminalApp::implementation { uint32_t TerminalSettings::GetColorTableEntry(int32_t index) const noexcept { diff --git a/src/cascadia/TerminalSettings/terminalsettings.h b/src/cascadia/TerminalApp/TerminalSettings.h similarity index 84% rename from src/cascadia/TerminalSettings/terminalsettings.h rename to src/cascadia/TerminalApp/TerminalSettings.h index 1bd1aad98a..02998373e7 100644 --- a/src/cascadia/TerminalSettings/terminalsettings.h +++ b/src/cascadia/TerminalApp/TerminalSettings.h @@ -19,7 +19,7 @@ Author(s): #include #include -namespace winrt::Microsoft::Terminal::Settings::implementation +namespace winrt::TerminalApp::implementation { struct TerminalSettings : TerminalSettingsT { @@ -49,7 +49,7 @@ namespace winrt::Microsoft::Terminal::Settings::implementation GETSET_PROPERTY(bool, SnapOnInput, true); GETSET_PROPERTY(bool, AltGrAliasing, true); GETSET_PROPERTY(uint32_t, CursorColor, DEFAULT_CURSOR_COLOR); - GETSET_PROPERTY(CursorStyle, CursorShape, CursorStyle::Vintage); + GETSET_PROPERTY(Microsoft::Terminal::Settings::CursorStyle, CursorShape, Microsoft::Terminal::Settings::CursorStyle::Vintage); GETSET_PROPERTY(uint32_t, CursorHeight, DEFAULT_CURSOR_HEIGHT); GETSET_PROPERTY(hstring, WordDelimiters, DEFAULT_WORD_DELIMITERS); GETSET_PROPERTY(bool, CopyOnSelect, false); @@ -78,7 +78,7 @@ namespace winrt::Microsoft::Terminal::Settings::implementation BackgroundImageVerticalAlignment, winrt::Windows::UI::Xaml::VerticalAlignment::Center); - GETSET_PROPERTY(IKeyBindings, KeyBindings, nullptr); + GETSET_PROPERTY(Microsoft::Terminal::Settings::IKeyBindings, KeyBindings, nullptr); GETSET_PROPERTY(hstring, Commandline); GETSET_PROPERTY(hstring, StartingDirectory); @@ -86,9 +86,9 @@ namespace winrt::Microsoft::Terminal::Settings::implementation GETSET_PROPERTY(bool, SuppressApplicationTitle); GETSET_PROPERTY(hstring, EnvironmentVariables); - GETSET_PROPERTY(ScrollbarState, ScrollState, ScrollbarState::Visible); + GETSET_PROPERTY(Microsoft::Terminal::Settings::ScrollbarState, ScrollState, Microsoft::Terminal::Settings::ScrollbarState::Visible); - GETSET_PROPERTY(TextAntialiasingMode, AntialiasingMode, TextAntialiasingMode::Grayscale); + GETSET_PROPERTY(Microsoft::Terminal::Settings::TextAntialiasingMode, AntialiasingMode, Microsoft::Terminal::Settings::TextAntialiasingMode::Grayscale); GETSET_PROPERTY(bool, RetroTerminalEffect, false); GETSET_PROPERTY(bool, ForceFullRepaintRendering, false); @@ -102,7 +102,7 @@ namespace winrt::Microsoft::Terminal::Settings::implementation }; } -namespace winrt::Microsoft::Terminal::Settings::factory_implementation +namespace winrt::TerminalApp::factory_implementation { BASIC_FACTORY(TerminalSettings); } diff --git a/src/cascadia/TerminalSettings/TerminalSettings.idl b/src/cascadia/TerminalApp/TerminalSettings.idl similarity index 75% rename from src/cascadia/TerminalSettings/TerminalSettings.idl rename to src/cascadia/TerminalApp/TerminalSettings.idl index 15d265b1a9..3d7d488010 100644 --- a/src/cascadia/TerminalSettings/TerminalSettings.idl +++ b/src/cascadia/TerminalApp/TerminalSettings.idl @@ -1,10 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. -import "ICoreSettings.idl"; -import "IControlSettings.idl"; - -namespace Microsoft.Terminal.Settings +namespace TerminalApp { // Class Description: // TerminalSettings encapsulates all settings that control the @@ -15,8 +12,8 @@ namespace Microsoft.Terminal.Settings // The TerminalControl will pull settings it requires from this object, // and pass along the Core properties to the terminal core. [default_interface] - runtimeclass TerminalSettings : ICoreSettings, - IControlSettings + runtimeclass TerminalSettings : Microsoft.Terminal.Settings.ICoreSettings, + Microsoft.Terminal.Settings.IControlSettings { TerminalSettings(); }; diff --git a/src/cascadia/TerminalApp/lib/TerminalAppLib.vcxproj b/src/cascadia/TerminalApp/lib/TerminalAppLib.vcxproj index 0fb6b823c4..2ceada4ea3 100644 --- a/src/cascadia/TerminalApp/lib/TerminalAppLib.vcxproj +++ b/src/cascadia/TerminalApp/lib/TerminalAppLib.vcxproj @@ -117,6 +117,9 @@ + + ../TerminalSettings.idl + ../ShortcutActionDispatch.idl @@ -186,6 +189,9 @@ + + ../TerminalSettings.idl + Create @@ -256,6 +262,7 @@ + diff --git a/src/cascadia/TerminalApp/lib/TerminalAppLib.vcxproj.filters b/src/cascadia/TerminalApp/lib/TerminalAppLib.vcxproj.filters index d716860a4a..fea379bc66 100644 --- a/src/cascadia/TerminalApp/lib/TerminalAppLib.vcxproj.filters +++ b/src/cascadia/TerminalApp/lib/TerminalAppLib.vcxproj.filters @@ -59,7 +59,7 @@ - + settings @@ -119,7 +119,7 @@ profileGeneration - + settings @@ -139,10 +139,14 @@ tab - commandPalette + + + + settings + @@ -198,4 +202,4 @@ app - + \ No newline at end of file diff --git a/src/cascadia/TerminalControl/TermControl.cpp b/src/cascadia/TerminalControl/TermControl.cpp index 784275fa32..62bc7a948e 100644 --- a/src/cascadia/TerminalControl/TermControl.cpp +++ b/src/cascadia/TerminalControl/TermControl.cpp @@ -56,11 +56,6 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation return initialized; } - TermControl::TermControl() : - TermControl(Settings::TerminalSettings{}, TerminalConnection::ITerminalConnection{ nullptr }) - { - } - TermControl::TermControl(Settings::IControlSettings settings, TerminalConnection::ITerminalConnection connection) : _connection{ connection }, _initializedTerminal{ false }, diff --git a/src/cascadia/TerminalControl/TermControl.h b/src/cascadia/TerminalControl/TermControl.h index 783ca85d96..4499c589ef 100644 --- a/src/cascadia/TerminalControl/TermControl.h +++ b/src/cascadia/TerminalControl/TermControl.h @@ -56,7 +56,6 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation struct TermControl : TermControlT { - TermControl(); TermControl(Settings::IControlSettings settings, TerminalConnection::ITerminalConnection connection); winrt::fire_and_forget UpdateSettings(Settings::IControlSettings newSettings); diff --git a/src/cascadia/TerminalControl/TermControl.idl b/src/cascadia/TerminalControl/TermControl.idl index d5454e5057..d9a2ac5cdf 100644 --- a/src/cascadia/TerminalControl/TermControl.idl +++ b/src/cascadia/TerminalControl/TermControl.idl @@ -32,7 +32,6 @@ namespace Microsoft.Terminal.TerminalControl [default_interface] runtimeclass TermControl : Windows.UI.Xaml.Controls.UserControl, IDirectKeyListener, IMouseWheelListener { - TermControl(); TermControl(Microsoft.Terminal.Settings.IControlSettings settings, Microsoft.Terminal.TerminalConnection.ITerminalConnection connection); static Windows.Foundation.Size GetProposedDimensions(Microsoft.Terminal.Settings.IControlSettings settings, UInt32 dpi); diff --git a/src/cascadia/TerminalCore/Terminal.cpp b/src/cascadia/TerminalCore/Terminal.cpp index e771950709..b71471fc7e 100644 --- a/src/cascadia/TerminalCore/Terminal.cpp +++ b/src/cascadia/TerminalCore/Terminal.cpp @@ -486,14 +486,14 @@ bool Terminal::SendKeyEvent(const WORD vkey, // - false if we did not translate the key, and it should be processed into a character. bool Terminal::SendMouseEvent(const COORD viewportPos, const unsigned int uiButton, const ControlKeyStates states, const short wheelDelta) { - // viewportPos must be within the dimensions of the viewport - const auto viewportDimensions = _mutableViewport.Dimensions(); - if (viewportPos.X < 0 || viewportPos.X >= viewportDimensions.X || viewportPos.Y < 0 || viewportPos.Y >= viewportDimensions.Y) - { - return false; - } - - return _terminalInput->HandleMouse(viewportPos, uiButton, GET_KEYSTATE_WPARAM(states.Value()), wheelDelta); + // GH#6401: VT applications should be able to receive mouse events from outside the + // terminal buffer. This is likely to happen when the user drags the cursor offscreen. + // We shouldn't throw away perfectly good events when they're offscreen, so we just + // clamp them to be within the range [(0, 0), (W, H)]. +#pragma warning(suppress : 26496) // analysis can't tell we're assigning through a reference below + auto clampedPos{ viewportPos }; + _mutableViewport.ToOrigin().Clamp(clampedPos); + return _terminalInput->HandleMouse(clampedPos, uiButton, GET_KEYSTATE_WPARAM(states.Value()), wheelDelta); } // Method Description: diff --git a/src/cascadia/TerminalSettings/TerminalSettings.vcxproj b/src/cascadia/TerminalSettings/TerminalSettings.vcxproj index 982de90ec2..eef3fe672f 100644 --- a/src/cascadia/TerminalSettings/TerminalSettings.vcxproj +++ b/src/cascadia/TerminalSettings/TerminalSettings.vcxproj @@ -17,18 +17,13 @@ --> true - - KeyChord.idl - - TerminalSettings.idl - @@ -37,13 +32,9 @@ KeyChord.idl - - TerminalSettings.idl - - @@ -53,6 +44,5 @@ - - + \ No newline at end of file diff --git a/src/interactivity/win32/windowio.cpp b/src/interactivity/win32/windowio.cpp index 023b14a859..2b65f51504 100644 --- a/src/interactivity/win32/windowio.cpp +++ b/src/interactivity/win32/windowio.cpp @@ -123,7 +123,14 @@ bool HandleTerminalMouseEvent(const COORD cMousePosition, // Virtual terminal input mode if (IsInVirtualTerminalInputMode()) { - fWasHandled = gci.GetActiveInputBuffer()->GetTerminalInput().HandleMouse(cMousePosition, uiButton, sModifierKeystate, sWheelDelta); + // GH#6401: VT applications should be able to receive mouse events from outside the + // terminal buffer. This is likely to happen when the user drags the cursor offscreen. + // We shouldn't throw away perfectly good events when they're offscreen, so we just + // clamp them to be within the range [(0, 0), (W, H)]. + auto clampedPosition{ cMousePosition }; + const auto clampViewport{ gci.GetActiveOutputBuffer().GetViewport().ToOrigin() }; + clampViewport.Clamp(clampedPosition); + fWasHandled = gci.GetActiveInputBuffer()->GetTerminalInput().HandleMouse(clampedPosition, uiButton, sModifierKeystate, sWheelDelta); } return fWasHandled; @@ -635,6 +642,25 @@ BOOL HandleMouseEvent(const SCREEN_INFORMATION& ScreenInfo, if (HandleTerminalMouseEvent(MousePosition, Message, GET_KEYSTATE_WPARAM(wParam), sDelta)) { + // GH#6401: Capturing the mouse ensures that we get drag/release events + // even if the user moves outside the window. + // HandleTerminalMouseEvent returns false if the terminal's not in VT mode, + // so capturing/releasing here should not impact other console mouse event + // consumers. + switch (Message) + { + case WM_LBUTTONDOWN: + case WM_MBUTTONDOWN: + case WM_RBUTTONDOWN: + SetCapture(ServiceLocator::LocateConsoleWindow()->GetWindowHandle()); + break; + case WM_LBUTTONUP: + case WM_MBUTTONUP: + case WM_RBUTTONUP: + ReleaseCapture(); + break; + } + return FALSE; } }