From dae733a22d0612b5ea9e70cf2b680391b439b637 Mon Sep 17 00:00:00 2001 From: zadjii Date: Tue, 24 Mar 2020 11:12:23 -0500 Subject: [PATCH 01/18] try naively passing the mouse event through, but that doesn't seem to do the trick --- src/cascadia/WindowsTerminal/AppHost.cpp | 11 ++++- src/cascadia/WindowsTerminal/AppHost.h | 1 + src/cascadia/WindowsTerminal/IslandWindow.cpp | 47 +++++++++++++++++++ src/cascadia/WindowsTerminal/IslandWindow.h | 1 + 4 files changed, 59 insertions(+), 1 deletion(-) diff --git a/src/cascadia/WindowsTerminal/AppHost.cpp b/src/cascadia/WindowsTerminal/AppHost.cpp index 2959b22220e..24fa2d7d652 100644 --- a/src/cascadia/WindowsTerminal/AppHost.cpp +++ b/src/cascadia/WindowsTerminal/AppHost.cpp @@ -51,7 +51,7 @@ AppHost::AppHost() noexcept : _logic, std::placeholders::_1, std::placeholders::_2)); - + _window->MouseScrolled({ this, &AppHost::_WindowMouseWheeled}); _window->MakeWindow(); } @@ -338,3 +338,12 @@ void AppHost::_ToggleFullscreen(const winrt::Windows::Foundation::IInspectable&, { _window->ToggleFullscreen(); } + +void AppHost::_WindowMouseWheeled(const bool isHorizontalScroll, const float delta) +{ + isHorizontalScroll; + delta; + // auto root = _logic.GetRoot(); + // root. + // root.as(); +} diff --git a/src/cascadia/WindowsTerminal/AppHost.h b/src/cascadia/WindowsTerminal/AppHost.h index 90b65b21c24..c535b9ccdcb 100644 --- a/src/cascadia/WindowsTerminal/AppHost.h +++ b/src/cascadia/WindowsTerminal/AppHost.h @@ -35,4 +35,5 @@ class AppHost const winrt::Windows::UI::Xaml::ElementTheme& arg); void _ToggleFullscreen(const winrt::Windows::Foundation::IInspectable& sender, const winrt::TerminalApp::ToggleFullscreenEventArgs& arg); + void _WindowMouseWheeled(const bool isHorizontalScroll, const float delta); }; diff --git a/src/cascadia/WindowsTerminal/IslandWindow.cpp b/src/cascadia/WindowsTerminal/IslandWindow.cpp index 0584711c7a7..34950195545 100644 --- a/src/cascadia/WindowsTerminal/IslandWindow.cpp +++ b/src/cascadia/WindowsTerminal/IslandWindow.cpp @@ -264,6 +264,19 @@ void IslandWindow::OnSize(const UINT width, const UINT height) } } +struct MyMsg { + UINT message; + WPARAM wparam; + LPARAM lparam; +}; + +BOOL CALLBACK okay(HWND child, LPARAM lp) +{ + MyMsg m = *((MyMsg*)lp); + PostMessage(child, m.message, m.wparam, m.lparam); + return false; +} + [[nodiscard]] LRESULT IslandWindow::MessageHandler(UINT const message, WPARAM const wparam, LPARAM const lparam) noexcept { switch (message) @@ -326,8 +339,42 @@ void IslandWindow::OnSize(const UINT width, const UINT height) _windowCloseButtonClickedHandler(); return 0; } + case WM_MOUSEWHEEL: + case WM_MOUSEHWHEEL: + { + bool isMouseWheel = message == WM_MOUSEWHEEL; + bool isMouseHWheel = message == WM_MOUSEHWHEEL; + if (isMouseWheel || isMouseHWheel) + { + short wheelDelta = (short)HIWORD(wparam); + bool hasShift = (wparam & MK_SHIFT) ? true : false; + wheelDelta; + hasShift; + auto a = 0; + a++; + a; + // _MouseScrolledHandlers(isMouseHWheel, wheelDelta); + auto f = [&message, & wparam, & lparam](HWND child, LPARAM /*lp*/) -> BOOL { + PostMessage(child, message, wparam, lparam); + return false; + }; + MyMsg m{ message, wparam, lparam }; + EnumChildWindows(_interopWindowHandle, okay, (LPARAM)&m); + // PostMessage(_interopWindowHandle, message, wparam, lparam); + return 0; + // Scrolling::s_HandleMouseWheel(isMouseWheel, + // isMouseHWheel, + // wheelDelta, + // hasShift, + // ScreenInfo); + } + break; + + } } + + // TODO: handle messages here... return base_type::MessageHandler(message, wparam, lparam); } diff --git a/src/cascadia/WindowsTerminal/IslandWindow.h b/src/cascadia/WindowsTerminal/IslandWindow.h index 432b78c3142..d8433d7948c 100644 --- a/src/cascadia/WindowsTerminal/IslandWindow.h +++ b/src/cascadia/WindowsTerminal/IslandWindow.h @@ -72,6 +72,7 @@ class IslandWindow : DECLARE_EVENT(DragRegionClicked, _DragRegionClickedHandlers, winrt::delegate<>); DECLARE_EVENT(WindowCloseButtonClicked, _windowCloseButtonClickedHandler, winrt::delegate<>); + WINRT_CALLBACK(MouseScrolled, winrt::delegate); protected: void ForceResize() From 892bc58ecf91a5bdcae8c3fde7ea24010893164b Mon Sep 17 00:00:00 2001 From: zadjii Date: Tue, 24 Mar 2020 11:19:34 -0500 Subject: [PATCH 02/18] doing this the right way still isn't right --- src/cascadia/WindowsTerminal/IslandWindow.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/cascadia/WindowsTerminal/IslandWindow.cpp b/src/cascadia/WindowsTerminal/IslandWindow.cpp index 34950195545..0b9cbda576a 100644 --- a/src/cascadia/WindowsTerminal/IslandWindow.cpp +++ b/src/cascadia/WindowsTerminal/IslandWindow.cpp @@ -274,7 +274,9 @@ BOOL CALLBACK okay(HWND child, LPARAM lp) { MyMsg m = *((MyMsg*)lp); PostMessage(child, m.message, m.wparam, m.lparam); - return false; + + return true; + } [[nodiscard]] LRESULT IslandWindow::MessageHandler(UINT const message, WPARAM const wparam, LPARAM const lparam) noexcept From b708a08e5c012a69957b74127c1adbc6010f926b Mon Sep 17 00:00:00 2001 From: zadjii Date: Tue, 24 Mar 2020 12:34:49 -0500 Subject: [PATCH 03/18] start working on manually plumbing the event through, but this feels so very wrong --- src/cascadia/TerminalApp/AppLogic.idl | 3 ++- .../TerminalApp/IMouseWheelListener.idl | 17 +++++++++++++ src/cascadia/TerminalControl/TermControl.cpp | 21 ++++++++++++++++ src/cascadia/TerminalControl/TermControl.h | 3 +++ src/cascadia/TerminalControl/TermControl.idl | 14 ++++++++++- src/cascadia/WindowsTerminal/AppHost.cpp | 3 ++- src/cascadia/WindowsTerminal/AppHost.h | 2 +- src/cascadia/WindowsTerminal/IslandWindow.cpp | 25 +++++++++++++------ src/cascadia/WindowsTerminal/IslandWindow.h | 2 +- 9 files changed, 78 insertions(+), 12 deletions(-) create mode 100644 src/cascadia/TerminalApp/IMouseWheelListener.idl diff --git a/src/cascadia/TerminalApp/AppLogic.idl b/src/cascadia/TerminalApp/AppLogic.idl index 1fecbfb34bd..b2deaee5126 100644 --- a/src/cascadia/TerminalApp/AppLogic.idl +++ b/src/cascadia/TerminalApp/AppLogic.idl @@ -4,6 +4,7 @@ import "../TerminalPage.idl"; import "../ShortcutActionDispatch.idl"; import "../IF7Listener.idl"; +import "../IMouseWheelListener.idl"; namespace TerminalApp { @@ -13,7 +14,7 @@ namespace TerminalApp MaximizedMode, }; - [default_interface] runtimeclass AppLogic: IF7Listener { + [default_interface] runtimeclass AppLogic: IF7Listener, IMouseWheelListener { AppLogic(); // For your own sanity, it's better to do setup outside the ctor. diff --git a/src/cascadia/TerminalApp/IMouseWheelListener.idl b/src/cascadia/TerminalApp/IMouseWheelListener.idl new file mode 100644 index 00000000000..b37d3e7490d --- /dev/null +++ b/src/cascadia/TerminalApp/IMouseWheelListener.idl @@ -0,0 +1,17 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +namespace TerminalApp +{ + // C++/winrt makes it difficult to share this idl between two projects, + // Instead, we just pin the uuid and include it in both TermControl and App + // If you update this one, please update the one in TerminalControl\TermControl.idl + // If you change this interface, please update the guid. + // If you mousewheel and get a runtime error, go make sure both copies are the same. + [uuid("65b8b8c5-988f-43ff-aba9-e89368da1598")] + interface IMouseWheelListener + { + Boolean OnMouseWheel(Windows.Foundation.Point location, Single delta); + Boolean OnMouseHWheel(Windows.Foundation.Point location, Single delta); + } +} diff --git a/src/cascadia/TerminalControl/TermControl.cpp b/src/cascadia/TerminalControl/TermControl.cpp index 0d955716ca0..1921712171d 100644 --- a/src/cascadia/TerminalControl/TermControl.cpp +++ b/src/cascadia/TerminalControl/TermControl.cpp @@ -2362,6 +2362,27 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation e.DragUIOverride().IsGlyphVisible(false); } + + bool TermControl::OnMouseWheel(Windows::Foundation::Point location, float delta) + { + location; + delta; + auto a = 0; + a++; + a; + return false; + } + bool TermControl::OnMouseHWheel(Windows::Foundation::Point location, float delta) + { + location; + delta; + auto a = 0; + a++; + a; + return false; + + } + // -------------------------------- WinRT Events --------------------------------- // Winrt events need a method for adding a callback to the event and removing the callback. // These macros will define them both for you. diff --git a/src/cascadia/TerminalControl/TermControl.h b/src/cascadia/TerminalControl/TermControl.h index 57606506bee..34d0ef5f3ed 100644 --- a/src/cascadia/TerminalControl/TermControl.h +++ b/src/cascadia/TerminalControl/TermControl.h @@ -83,6 +83,9 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation bool OnF7Pressed(); + bool OnMouseWheel(Windows::Foundation::Point location, float delta); + bool OnMouseHWheel(Windows::Foundation::Point location, float delta); + ~TermControl(); Windows::UI::Xaml::Automation::Peers::AutomationPeer OnCreateAutomationPeer(); diff --git a/src/cascadia/TerminalControl/TermControl.idl b/src/cascadia/TerminalControl/TermControl.idl index a005ac16d5a..0bcdc8f3267 100644 --- a/src/cascadia/TerminalControl/TermControl.idl +++ b/src/cascadia/TerminalControl/TermControl.idl @@ -18,6 +18,18 @@ namespace Microsoft.Terminal.TerminalControl Boolean OnF7Pressed(); } + // C++/winrt makes it difficult to share this idl between two projects, + // Instead, we just pin the uuid and include it in both TermControl and App + // If you update this one, please update the one in TerminalControl\TermControl.idl + // If you change this interface, please update the guid. + // If you mousewheel and get a runtime error, go make sure both copies are the same. + [uuid("65b8b8c5-988f-43ff-aba9-e89368da1598")] + interface IMouseWheelListener + { + Boolean OnMouseWheel(Windows.Foundation.Point location, Single delta); + Boolean OnMouseHWheel(Windows.Foundation.Point location, Single delta); + } + runtimeclass CopyToClipboardEventArgs { String Text { get; }; @@ -30,7 +42,7 @@ namespace Microsoft.Terminal.TerminalControl void HandleClipboardData(String data); } - [default_interface] runtimeclass TermControl : Windows.UI.Xaml.Controls.UserControl, IF7Listener + [default_interface] runtimeclass TermControl : Windows.UI.Xaml.Controls.UserControl, IF7Listener, IMouseWheelListener { TermControl(); TermControl(Microsoft.Terminal.Settings.IControlSettings settings, Microsoft.Terminal.TerminalConnection.ITerminalConnection connection); diff --git a/src/cascadia/WindowsTerminal/AppHost.cpp b/src/cascadia/WindowsTerminal/AppHost.cpp index 24fa2d7d652..f2a66e8747e 100644 --- a/src/cascadia/WindowsTerminal/AppHost.cpp +++ b/src/cascadia/WindowsTerminal/AppHost.cpp @@ -339,10 +339,11 @@ void AppHost::_ToggleFullscreen(const winrt::Windows::Foundation::IInspectable&, _window->ToggleFullscreen(); } -void AppHost::_WindowMouseWheeled(const bool isHorizontalScroll, const float delta) +void AppHost::_WindowMouseWheeled(const til::point coord, const bool isHorizontalScroll, const float delta) { isHorizontalScroll; delta; + _logic.OnMouseWheel(); // auto root = _logic.GetRoot(); // root. // root.as(); diff --git a/src/cascadia/WindowsTerminal/AppHost.h b/src/cascadia/WindowsTerminal/AppHost.h index c535b9ccdcb..0cfcf7961a5 100644 --- a/src/cascadia/WindowsTerminal/AppHost.h +++ b/src/cascadia/WindowsTerminal/AppHost.h @@ -35,5 +35,5 @@ class AppHost const winrt::Windows::UI::Xaml::ElementTheme& arg); void _ToggleFullscreen(const winrt::Windows::Foundation::IInspectable& sender, const winrt::TerminalApp::ToggleFullscreenEventArgs& arg); - void _WindowMouseWheeled(const bool isHorizontalScroll, const float delta); + void _WindowMouseWheeled(const til::point coord, const bool isHorizontalScroll, const float delta); }; diff --git a/src/cascadia/WindowsTerminal/IslandWindow.cpp b/src/cascadia/WindowsTerminal/IslandWindow.cpp index 0b9cbda576a..d27e1c7e441 100644 --- a/src/cascadia/WindowsTerminal/IslandWindow.cpp +++ b/src/cascadia/WindowsTerminal/IslandWindow.cpp @@ -348,20 +348,31 @@ BOOL CALLBACK okay(HWND child, LPARAM lp) bool isMouseHWheel = message == WM_MOUSEHWHEEL; if (isMouseWheel || isMouseHWheel) { + // https://msdn.microsoft.com/en-us/library/windows/desktop/ms645617(v=vs.85).aspx + // Important Do not use the LOWORD or HIWORD macros to extract the x- and y- + // coordinates of the cursor position because these macros return incorrect + // results on systems with multiple monitors. Systems with multiple monitors + // can have negative x- and y- coordinates, and LOWORD and HIWORD treat the + // coordinates as unsigned quantities. + short x = GET_X_LPARAM(lparam); + short y = GET_Y_LPARAM(lparam); + short wheelDelta = (short)HIWORD(wparam); + bool hasShift = (wparam & MK_SHIFT) ? true : false; wheelDelta; hasShift; + auto a = 0; a++; a; - // _MouseScrolledHandlers(isMouseHWheel, wheelDelta); - auto f = [&message, & wparam, & lparam](HWND child, LPARAM /*lp*/) -> BOOL { - PostMessage(child, message, wparam, lparam); - return false; - }; - MyMsg m{ message, wparam, lparam }; - EnumChildWindows(_interopWindowHandle, okay, (LPARAM)&m); + _MouseScrolledHandlers(til::point{x, y}, isMouseHWheel, wheelDelta); + // auto f = [&message, & wparam, & lparam](HWND child, LPARAM /*lp*/) -> BOOL { + // PostMessage(child, message, wparam, lparam); + // return false; + // }; + // MyMsg m{ message, wparam, lparam }; + // EnumChildWindows(_interopWindowHandle, okay, (LPARAM)&m); // PostMessage(_interopWindowHandle, message, wparam, lparam); return 0; // Scrolling::s_HandleMouseWheel(isMouseWheel, diff --git a/src/cascadia/WindowsTerminal/IslandWindow.h b/src/cascadia/WindowsTerminal/IslandWindow.h index d8433d7948c..02a68b2c923 100644 --- a/src/cascadia/WindowsTerminal/IslandWindow.h +++ b/src/cascadia/WindowsTerminal/IslandWindow.h @@ -72,7 +72,7 @@ class IslandWindow : DECLARE_EVENT(DragRegionClicked, _DragRegionClickedHandlers, winrt::delegate<>); DECLARE_EVENT(WindowCloseButtonClicked, _windowCloseButtonClickedHandler, winrt::delegate<>); - WINRT_CALLBACK(MouseScrolled, winrt::delegate); + WINRT_CALLBACK(MouseScrolled, winrt::delegate); protected: void ForceResize() From 68ace1abc6cc56f786f8be77bff0dbbeb4735237 Mon Sep 17 00:00:00 2001 From: zadjii-msft Date: Tue, 24 Mar 2020 13:30:32 -0500 Subject: [PATCH 04/18] This is so dumb ; I love it Just ask for the control underneath the mouse where it scrolled, and dispatch a scroll event to it if it matches the given interface. --- src/cascadia/TerminalApp/AppLogic.cpp | 34 ++++++++++++++++++++++++ src/cascadia/TerminalApp/AppLogic.h | 3 +++ src/cascadia/WindowsTerminal/AppHost.cpp | 26 +++++++++++++++++- src/cascadia/WindowsTerminal/pch.h | 2 ++ src/inc/til/point.h | 10 +++++++ 5 files changed, 74 insertions(+), 1 deletion(-) diff --git a/src/cascadia/TerminalApp/AppLogic.cpp b/src/cascadia/TerminalApp/AppLogic.cpp index c45d7ca2f0b..ae9d7b9ea96 100644 --- a/src/cascadia/TerminalApp/AppLogic.cpp +++ b/src/cascadia/TerminalApp/AppLogic.cpp @@ -842,6 +842,40 @@ namespace winrt::TerminalApp::implementation return { L"" }; } + + bool AppLogic::OnMouseWheel(Windows::Foundation::Point location, float delta) + { + location; + delta; + auto a = 0; + a++; + a; + // if (!_root) + // { + // return false; + // } + // auto elems = winrt::Windows::UI::Xaml::Media::VisualTreeHelper::FindElementInHostCoordinates(location, _root); + // for (const auto& e : elems) + // { + // auto control = e.try_as(); + // if (control) + // { + // control.OnMouseWheel(location, delta); + // } + // } + return false; + } + bool AppLogic::OnMouseHWheel(Windows::Foundation::Point location, float delta) + { + location; + delta; + auto a = 0; + a++; + a; + return false; + + } + // -------------------------------- WinRT Events --------------------------------- // Winrt events need a method for adding a callback to the event and removing the callback. // These macros will define them both for you. diff --git a/src/cascadia/TerminalApp/AppLogic.h b/src/cascadia/TerminalApp/AppLogic.h index 99a8b93915b..45fb41f26f4 100644 --- a/src/cascadia/TerminalApp/AppLogic.h +++ b/src/cascadia/TerminalApp/AppLogic.h @@ -41,6 +41,9 @@ namespace winrt::TerminalApp::implementation void TitlebarClicked(); bool OnF7Pressed(); + bool OnMouseWheel(Windows::Foundation::Point location, float delta); + bool OnMouseHWheel(Windows::Foundation::Point location, float delta); + void WindowCloseButtonClicked(); // -------------------------------- WinRT Events --------------------------------- diff --git a/src/cascadia/WindowsTerminal/AppHost.cpp b/src/cascadia/WindowsTerminal/AppHost.cpp index f2a66e8747e..824fa3bf69d 100644 --- a/src/cascadia/WindowsTerminal/AppHost.cpp +++ b/src/cascadia/WindowsTerminal/AppHost.cpp @@ -17,6 +17,7 @@ using namespace winrt::Windows::Foundation::Numerics; using namespace ::Microsoft::Console; using namespace ::Microsoft::Console::Types; + AppHost::AppHost() noexcept : _app{}, _logic{ nullptr }, // don't make one, we're going to take a ref on app's @@ -343,7 +344,30 @@ void AppHost::_WindowMouseWheeled(const til::point coord, const bool isHorizonta { isHorizontalScroll; delta; - _logic.OnMouseWheel(); + // winrt::Windows::UI::Xaml::Media::VisualTreeHelper::FindElementsInHostCoordinates + + // winrt::Windows::Foundation::Point p{ coord }; + // coord.x + auto elems = winrt::Windows::UI::Xaml::Media::VisualTreeHelper::FindElementsInHostCoordinates(coord, _logic.GetRoot()); + for (const auto& e : elems) + { + auto control = e.try_as(); + if (control) + { + control.OnMouseWheel(coord, delta); + } + } + + // if (isHorizontalScroll) + // { + // _logic.OnMouseHWheel(coord, delta); + // } + // else + // { + // _logic.OnMouseWheel(coord, delta); + // } + + // auto root = _logic.GetRoot(); // root. // root.as(); diff --git a/src/cascadia/WindowsTerminal/pch.h b/src/cascadia/WindowsTerminal/pch.h index 275ec9a9239..318dbf35db0 100644 --- a/src/cascadia/WindowsTerminal/pch.h +++ b/src/cascadia/WindowsTerminal/pch.h @@ -30,6 +30,8 @@ Module Name: #include #include +#include + #include "../inc/LibraryIncludes.h" // This is inexplicable, but for whatever reason, cppwinrt conflicts with the diff --git a/src/inc/til/point.h b/src/inc/til/point.h index c7643b05286..52f25b578c5 100644 --- a/src/inc/til/point.h +++ b/src/inc/til/point.h @@ -193,6 +193,16 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned" } #endif +#ifdef WINRT_Windows_Foundation_H + operator winrt::Windows::Foundation::Point() const noexcept + { + winrt::Windows::Foundation::Point ret; + THROW_HR_IF(E_ABORT, !base::MakeCheckedNum(_x).AssignIfValid(&ret.X)); + THROW_HR_IF(E_ABORT, !base::MakeCheckedNum(_y).AssignIfValid(&ret.Y)); + return ret; + } +#endif + std::wstring to_string() const { return wil::str_printf(L"(X:%td, Y:%td)", x(), y()); From 7252ab6dbfbb5c639f36b6694143431c5ca624d3 Mon Sep 17 00:00:00 2001 From: zadjii-msft Date: Tue, 24 Mar 2020 16:54:40 -0500 Subject: [PATCH 05/18] Hey if your laptop's clock batttery is broken, you're going to have IMMENSE PAIN trying to work on this project. This doesn't work, but it's taking me like 5x as long to do anything on this laptop --- src/cascadia/TerminalApp/AppLogic.cpp | 34 ----------- src/cascadia/TerminalApp/AppLogic.h | 3 - src/cascadia/TerminalApp/AppLogic.idl | 3 +- .../TerminalApp/IMouseWheelListener.idl | 17 ------ src/cascadia/TerminalApp/TerminalPage.cpp | 2 +- src/cascadia/TerminalApp/lib/pch.h | 5 ++ src/cascadia/TerminalConnection/pch.h | 7 ++- .../TerminalControl/IMouseWheelListener.idl | 12 ++++ src/cascadia/TerminalControl/TermControl.idl | 14 +---- src/cascadia/TerminalControl/pch.h | 4 ++ src/cascadia/WindowsTerminal/AppHost.cpp | 22 ++++---- src/cascadia/WindowsTerminal/IslandWindow.cpp | 56 +++++++------------ src/cascadia/WindowsTerminal/pch.h | 6 +- 13 files changed, 66 insertions(+), 119 deletions(-) delete mode 100644 src/cascadia/TerminalApp/IMouseWheelListener.idl create mode 100644 src/cascadia/TerminalControl/IMouseWheelListener.idl diff --git a/src/cascadia/TerminalApp/AppLogic.cpp b/src/cascadia/TerminalApp/AppLogic.cpp index ae9d7b9ea96..c45d7ca2f0b 100644 --- a/src/cascadia/TerminalApp/AppLogic.cpp +++ b/src/cascadia/TerminalApp/AppLogic.cpp @@ -842,40 +842,6 @@ namespace winrt::TerminalApp::implementation return { L"" }; } - - bool AppLogic::OnMouseWheel(Windows::Foundation::Point location, float delta) - { - location; - delta; - auto a = 0; - a++; - a; - // if (!_root) - // { - // return false; - // } - // auto elems = winrt::Windows::UI::Xaml::Media::VisualTreeHelper::FindElementInHostCoordinates(location, _root); - // for (const auto& e : elems) - // { - // auto control = e.try_as(); - // if (control) - // { - // control.OnMouseWheel(location, delta); - // } - // } - return false; - } - bool AppLogic::OnMouseHWheel(Windows::Foundation::Point location, float delta) - { - location; - delta; - auto a = 0; - a++; - a; - return false; - - } - // -------------------------------- WinRT Events --------------------------------- // Winrt events need a method for adding a callback to the event and removing the callback. // These macros will define them both for you. diff --git a/src/cascadia/TerminalApp/AppLogic.h b/src/cascadia/TerminalApp/AppLogic.h index 45fb41f26f4..99a8b93915b 100644 --- a/src/cascadia/TerminalApp/AppLogic.h +++ b/src/cascadia/TerminalApp/AppLogic.h @@ -41,9 +41,6 @@ namespace winrt::TerminalApp::implementation void TitlebarClicked(); bool OnF7Pressed(); - bool OnMouseWheel(Windows::Foundation::Point location, float delta); - bool OnMouseHWheel(Windows::Foundation::Point location, float delta); - void WindowCloseButtonClicked(); // -------------------------------- WinRT Events --------------------------------- diff --git a/src/cascadia/TerminalApp/AppLogic.idl b/src/cascadia/TerminalApp/AppLogic.idl index b2deaee5126..1fecbfb34bd 100644 --- a/src/cascadia/TerminalApp/AppLogic.idl +++ b/src/cascadia/TerminalApp/AppLogic.idl @@ -4,7 +4,6 @@ import "../TerminalPage.idl"; import "../ShortcutActionDispatch.idl"; import "../IF7Listener.idl"; -import "../IMouseWheelListener.idl"; namespace TerminalApp { @@ -14,7 +13,7 @@ namespace TerminalApp MaximizedMode, }; - [default_interface] runtimeclass AppLogic: IF7Listener, IMouseWheelListener { + [default_interface] runtimeclass AppLogic: IF7Listener { AppLogic(); // For your own sanity, it's better to do setup outside the ctor. diff --git a/src/cascadia/TerminalApp/IMouseWheelListener.idl b/src/cascadia/TerminalApp/IMouseWheelListener.idl deleted file mode 100644 index b37d3e7490d..00000000000 --- a/src/cascadia/TerminalApp/IMouseWheelListener.idl +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT license. - -namespace TerminalApp -{ - // C++/winrt makes it difficult to share this idl between two projects, - // Instead, we just pin the uuid and include it in both TermControl and App - // If you update this one, please update the one in TerminalControl\TermControl.idl - // If you change this interface, please update the guid. - // If you mousewheel and get a runtime error, go make sure both copies are the same. - [uuid("65b8b8c5-988f-43ff-aba9-e89368da1598")] - interface IMouseWheelListener - { - Boolean OnMouseWheel(Windows.Foundation.Point location, Single delta); - Boolean OnMouseHWheel(Windows.Foundation.Point location, Single delta); - } -} diff --git a/src/cascadia/TerminalApp/TerminalPage.cpp b/src/cascadia/TerminalApp/TerminalPage.cpp index e7494424062..0ed15db8220 100644 --- a/src/cascadia/TerminalApp/TerminalPage.cpp +++ b/src/cascadia/TerminalApp/TerminalPage.cpp @@ -630,7 +630,7 @@ namespace winrt::TerminalApp::implementation settings.InitialRows(), settings.InitialCols(), winrt::guid()); - sessionGuid = conhostConn.Guid(); + sessionGuid = (GUID)conhostConn.Guid(); connection = conhostConn; } diff --git a/src/cascadia/TerminalApp/lib/pch.h b/src/cascadia/TerminalApp/lib/pch.h index 5fab170bda3..3c0ef0a73a1 100644 --- a/src/cascadia/TerminalApp/lib/pch.h +++ b/src/cascadia/TerminalApp/lib/pch.h @@ -9,6 +9,8 @@ #define WIN32_LEAN_AND_MEAN +// Manually include til after we include Windows.Foundation to give it winrt superpowers +#define BLOCK_TIL #include // This is inexplicable, but for whatever reason, cppwinrt conflicts with the // SDK definition of this function, so the only fix is to undef it. @@ -63,3 +65,6 @@ TRACELOGGING_DECLARE_PROVIDER(g_hTerminalAppProvider); #include #include + +// Manually include til after we include Windows.Foundation to give it winrt superpowers +#include "til.h" diff --git a/src/cascadia/TerminalConnection/pch.h b/src/cascadia/TerminalConnection/pch.h index 38ababb5a83..1550c51ca4e 100644 --- a/src/cascadia/TerminalConnection/pch.h +++ b/src/cascadia/TerminalConnection/pch.h @@ -12,14 +12,15 @@ #define BLOCK_GSL +// Manually include til after we include Windows.Foundation to give it winrt superpowers +#define BLOCK_TIL #include // Must be included before any WinRT headers. #include - +#include #include -#include "winrt/Windows.Foundation.h" #include "winrt/Windows.Security.Credentials.h" #include "winrt/Windows.Foundation.Collections.h" #include @@ -27,3 +28,5 @@ #include TRACELOGGING_DECLARE_PROVIDER(g_hTerminalConnectionProvider); #include + +#include "til.h" diff --git a/src/cascadia/TerminalControl/IMouseWheelListener.idl b/src/cascadia/TerminalControl/IMouseWheelListener.idl new file mode 100644 index 00000000000..db30bc9699d --- /dev/null +++ b/src/cascadia/TerminalControl/IMouseWheelListener.idl @@ -0,0 +1,12 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +namespace Microsoft.Terminal.TerminalControl +{ + [uuid("65b8b8c5-988f-43ff-aba9-e89368da1598")] + interface IMouseWheelListener + { + Boolean OnMouseWheel(Windows.Foundation.Point coord, Single delta); + Boolean OnMouseHWheel(Windows.Foundation.Point coord, Single delta); + } +} diff --git a/src/cascadia/TerminalControl/TermControl.idl b/src/cascadia/TerminalControl/TermControl.idl index 0bcdc8f3267..1a24a136011 100644 --- a/src/cascadia/TerminalControl/TermControl.idl +++ b/src/cascadia/TerminalControl/TermControl.idl @@ -1,6 +1,8 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. +import "IMouseWheelListener.idl"; + namespace Microsoft.Terminal.TerminalControl { delegate void TitleChangedEventArgs(String newTitle); @@ -18,18 +20,6 @@ namespace Microsoft.Terminal.TerminalControl Boolean OnF7Pressed(); } - // C++/winrt makes it difficult to share this idl between two projects, - // Instead, we just pin the uuid and include it in both TermControl and App - // If you update this one, please update the one in TerminalControl\TermControl.idl - // If you change this interface, please update the guid. - // If you mousewheel and get a runtime error, go make sure both copies are the same. - [uuid("65b8b8c5-988f-43ff-aba9-e89368da1598")] - interface IMouseWheelListener - { - Boolean OnMouseWheel(Windows.Foundation.Point location, Single delta); - Boolean OnMouseHWheel(Windows.Foundation.Point location, Single delta); - } - runtimeclass CopyToClipboardEventArgs { String Text { get; }; diff --git a/src/cascadia/TerminalControl/pch.h b/src/cascadia/TerminalControl/pch.h index e14a5d46f3f..a22bf8a71b8 100644 --- a/src/cascadia/TerminalControl/pch.h +++ b/src/cascadia/TerminalControl/pch.h @@ -9,6 +9,8 @@ #define WIN32_LEAN_AND_MEAN +// Manually include til after we include Windows.Foundation to give it winrt superpowers +#define BLOCK_TIL #include // This is inexplicable, but for whatever reason, cppwinrt conflicts with the // SDK definition of this function, so the only fix is to undef it. @@ -46,3 +48,5 @@ #include TRACELOGGING_DECLARE_PROVIDER(g_hTerminalControlProvider); #include + +#include "til.h" diff --git a/src/cascadia/WindowsTerminal/AppHost.cpp b/src/cascadia/WindowsTerminal/AppHost.cpp index 824fa3bf69d..f1736b23563 100644 --- a/src/cascadia/WindowsTerminal/AppHost.cpp +++ b/src/cascadia/WindowsTerminal/AppHost.cpp @@ -345,27 +345,29 @@ void AppHost::_WindowMouseWheeled(const til::point coord, const bool isHorizonta isHorizontalScroll; delta; // winrt::Windows::UI::Xaml::Media::VisualTreeHelper::FindElementsInHostCoordinates - + winrt::guid foo; + GUID bar; + bar = foo; // winrt::Windows::Foundation::Point p{ coord }; // coord.x auto elems = winrt::Windows::UI::Xaml::Media::VisualTreeHelper::FindElementsInHostCoordinates(coord, _logic.GetRoot()); for (const auto& e : elems) { - auto control = e.try_as(); + auto control = e.try_as(); if (control) { control.OnMouseWheel(coord, delta); + if (isHorizontalScroll) + { + control.OnMouseHWheel(coord, delta); + } + else + { + control.OnMouseWheel(coord, delta); + } } } - // if (isHorizontalScroll) - // { - // _logic.OnMouseHWheel(coord, delta); - // } - // else - // { - // _logic.OnMouseWheel(coord, delta); - // } // auto root = _logic.GetRoot(); diff --git a/src/cascadia/WindowsTerminal/IslandWindow.cpp b/src/cascadia/WindowsTerminal/IslandWindow.cpp index d27e1c7e441..d24bebf3521 100644 --- a/src/cascadia/WindowsTerminal/IslandWindow.cpp +++ b/src/cascadia/WindowsTerminal/IslandWindow.cpp @@ -344,43 +344,27 @@ BOOL CALLBACK okay(HWND child, LPARAM lp) case WM_MOUSEWHEEL: case WM_MOUSEHWHEEL: { - bool isMouseWheel = message == WM_MOUSEWHEEL; bool isMouseHWheel = message == WM_MOUSEHWHEEL; - if (isMouseWheel || isMouseHWheel) - { - // https://msdn.microsoft.com/en-us/library/windows/desktop/ms645617(v=vs.85).aspx - // Important Do not use the LOWORD or HIWORD macros to extract the x- and y- - // coordinates of the cursor position because these macros return incorrect - // results on systems with multiple monitors. Systems with multiple monitors - // can have negative x- and y- coordinates, and LOWORD and HIWORD treat the - // coordinates as unsigned quantities. - short x = GET_X_LPARAM(lparam); - short y = GET_Y_LPARAM(lparam); - - short wheelDelta = (short)HIWORD(wparam); - - bool hasShift = (wparam & MK_SHIFT) ? true : false; - wheelDelta; - hasShift; - - auto a = 0; - a++; - a; - _MouseScrolledHandlers(til::point{x, y}, isMouseHWheel, wheelDelta); - // auto f = [&message, & wparam, & lparam](HWND child, LPARAM /*lp*/) -> BOOL { - // PostMessage(child, message, wparam, lparam); - // return false; - // }; - // MyMsg m{ message, wparam, lparam }; - // EnumChildWindows(_interopWindowHandle, okay, (LPARAM)&m); - // PostMessage(_interopWindowHandle, message, wparam, lparam); - return 0; - // Scrolling::s_HandleMouseWheel(isMouseWheel, - // isMouseHWheel, - // wheelDelta, - // hasShift, - // ScreenInfo); - } + // https://msdn.microsoft.com/en-us/library/windows/desktop/ms645617(v=vs.85).aspx + // Important Do not use the LOWORD or HIWORD macros to extract the x- and y- + // coordinates of the cursor position because these macros return incorrect + // results on systems with multiple monitors. Systems with multiple monitors + // can have negative x- and y- coordinates, and LOWORD and HIWORD treat the + // coordinates as unsigned quantities. + short x = GET_X_LPARAM(lparam); + short y = GET_Y_LPARAM(lparam); + const til::point eventPoint{x, y}; + const til::rectangle windowRect{GetWindowRect()}; + const auto origin = windowRect.origin(); + auto relative = eventPoint-origin; + auto x1 = gsl::narrow_cast(relative.x() / GetCurrentDpiScale()); + auto y1 = gsl::narrow_cast(relative.y() / GetCurrentDpiScale()); + auto real = til::point{ x1, y1 }; + + short wheelDelta = (short)HIWORD(wparam); + + _MouseScrolledHandlers(real, isMouseHWheel, wheelDelta); + return 0; break; } diff --git a/src/cascadia/WindowsTerminal/pch.h b/src/cascadia/WindowsTerminal/pch.h index 318dbf35db0..1062d1bf7cb 100644 --- a/src/cascadia/WindowsTerminal/pch.h +++ b/src/cascadia/WindowsTerminal/pch.h @@ -30,8 +30,8 @@ Module Name: #include #include -#include - +// Manually include til after we include Windows.Foundation to give it winrt superpowers +#define BLOCK_TIL #include "../inc/LibraryIncludes.h" // This is inexplicable, but for whatever reason, cppwinrt conflicts with the @@ -69,3 +69,5 @@ TRACELOGGING_DECLARE_PROVIDER(g_hWindowsTerminalProvider); // For commandline argument processing #include #include + +#include "til.h" From b3da428e61892e7b07e2f6d280a89cd57567cb57 Mon Sep 17 00:00:00 2001 From: zadjii-msft Date: Wed, 25 Mar 2020 09:38:23 -0500 Subject: [PATCH 06/18] Boy this is such a dirty hack but hey it works --- .../TerminalControl/IMouseWheelListener.idl | 4 +- src/cascadia/TerminalControl/TermControl.cpp | 48 +++++++++---------- src/cascadia/TerminalControl/TermControl.h | 9 ++-- .../TerminalControl/TerminalControl.vcxproj | 1 + src/cascadia/WindowsTerminal/AppHost.cpp | 2 +- src/cascadia/WindowsTerminal/AppHost.h | 2 +- src/cascadia/WindowsTerminal/IslandWindow.cpp | 6 +++ src/cascadia/WindowsTerminal/IslandWindow.h | 2 +- 8 files changed, 42 insertions(+), 32 deletions(-) diff --git a/src/cascadia/TerminalControl/IMouseWheelListener.idl b/src/cascadia/TerminalControl/IMouseWheelListener.idl index db30bc9699d..2ac937da6eb 100644 --- a/src/cascadia/TerminalControl/IMouseWheelListener.idl +++ b/src/cascadia/TerminalControl/IMouseWheelListener.idl @@ -6,7 +6,7 @@ namespace Microsoft.Terminal.TerminalControl [uuid("65b8b8c5-988f-43ff-aba9-e89368da1598")] interface IMouseWheelListener { - Boolean OnMouseWheel(Windows.Foundation.Point coord, Single delta); - Boolean OnMouseHWheel(Windows.Foundation.Point coord, Single delta); + Boolean OnMouseWheel(Windows.Foundation.Point coord, Int32 delta); + Boolean OnMouseHWheel(Windows.Foundation.Point coord, Int32 delta); } } diff --git a/src/cascadia/TerminalControl/TermControl.cpp b/src/cascadia/TerminalControl/TermControl.cpp index 1921712171d..25fd1557326 100644 --- a/src/cascadia/TerminalControl/TermControl.cpp +++ b/src/cascadia/TerminalControl/TermControl.cpp @@ -1160,20 +1160,29 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation Input::PointerRoutedEventArgs const& args) { const auto point = args.GetCurrentPoint(*this); - - if (_CanSendVTMouseInput()) + auto result = _DoMouseWheel(point.Position(), static_cast(args.KeyModifiers()), point.Properties().MouseWheelDelta(), point.Properties().IsLeftButtonPressed()); + if (result) { - _TrySendMouseEvent(point); args.Handled(true); - return; } + } + + bool TermControl::_DoMouseWheel(const Windows::Foundation::Point point, const uint32_t modifiers, const int32_t delta, const bool isLeftButtonPressed) + { - const auto delta = point.Properties().MouseWheelDelta(); + if (_CanSendVTMouseInput()) + { + // GAH this used to be + // _TrySendMouseEvent(point); + // But we don't have a PointerPoint anymore. So we're going to fake that this is only a mousewheel. + const auto terminalPosition = _GetTerminalPosition(point); + unsigned int uiButton = WM_MOUSEWHEEL; + return _terminal->SendMouseEvent(terminalPosition, uiButton, _GetPressedModifierKeys(), ::base::saturated_cast(delta)); + } // Get the state of the Ctrl & Shift keys // static_cast to a uint32_t because we can't use the WI_IsFlagSet macro // directly with a VirtualKeyModifiers - const auto modifiers = static_cast(args.KeyModifiers()); const auto ctrlPressed = WI_IsFlagSet(modifiers, static_cast(VirtualKeyModifiers::Control)); const auto shiftPressed = WI_IsFlagSet(modifiers, static_cast(VirtualKeyModifiers::Shift)); @@ -1187,8 +1196,9 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation } else { - _MouseScrollHandler(delta, point); + _MouseScrollHandler(delta, point, isLeftButtonPressed); } + return false; } // Method Description: @@ -1261,7 +1271,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation // - Scroll the visible viewport in response to a mouse wheel event. // Arguments: // - mouseDelta: the mouse wheel delta that triggered this event. - void TermControl::_MouseScrollHandler(const double mouseDelta, Windows::UI::Input::PointerPoint const& pointerPoint) + void TermControl::_MouseScrollHandler(const double mouseDelta, const Windows::Foundation::Point point, const bool isLeftButtonPressed) { const auto currentOffset = ScrollBar().Value(); @@ -1278,11 +1288,11 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation // for us. ScrollBar().Value(newValue); - if (_terminal->IsSelectionActive() && pointerPoint.Properties().IsLeftButtonPressed()) + if (_terminal->IsSelectionActive() && isLeftButtonPressed) { // If user is mouse selecting and scrolls, they then point at new character. // Make sure selection reflects that immediately. - _SetEndSelectionPointAtCursor(pointerPoint.Position()); + _SetEndSelectionPointAtCursor(point); } } @@ -2363,24 +2373,14 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation } - bool TermControl::OnMouseWheel(Windows::Foundation::Point location, float delta) + bool TermControl::OnMouseWheel(Windows::Foundation::Point location, int32_t delta) { - location; - delta; - auto a = 0; - a++; - a; - return false; + // const auto modifiers = _GetPressedModifierKeys(); + return _DoMouseWheel(location, 0, delta, false); } - bool TermControl::OnMouseHWheel(Windows::Foundation::Point location, float delta) + bool TermControl::OnMouseHWheel(Windows::Foundation::Point /*location*/, int32_t /*delta*/) { - location; - delta; - auto a = 0; - a++; - a; return false; - } // -------------------------------- WinRT Events --------------------------------- diff --git a/src/cascadia/TerminalControl/TermControl.h b/src/cascadia/TerminalControl/TermControl.h index 34d0ef5f3ed..df869682727 100644 --- a/src/cascadia/TerminalControl/TermControl.h +++ b/src/cascadia/TerminalControl/TermControl.h @@ -83,8 +83,8 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation bool OnF7Pressed(); - bool OnMouseWheel(Windows::Foundation::Point location, float delta); - bool OnMouseHWheel(Windows::Foundation::Point location, float delta); + bool OnMouseWheel(Windows::Foundation::Point location, int32_t delta); + bool OnMouseHWheel(Windows::Foundation::Point location, int32_t delta); ~TermControl(); @@ -198,9 +198,10 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation void _TerminalTitleChanged(const std::wstring_view& wstr); winrt::fire_and_forget _TerminalScrollPositionChanged(const int viewTop, const int viewHeight, const int bufferSize); - void _MouseScrollHandler(const double delta, Windows::UI::Input::PointerPoint const& pointerPoint); + void _MouseScrollHandler(const double mouseDelta, const Windows::Foundation::Point point, const bool isLeftButtonPressed); void _MouseZoomHandler(const double delta); void _MouseTransparencyHandler(const double delta); + bool _DoMouseWheel(const Windows::Foundation::Point point, const uint32_t modifiers, const int32_t delta, const bool isLeftButtonPressed); bool _CapturePointer(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::Input::PointerRoutedEventArgs const& e); bool _ReleasePointerCapture(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::Input::PointerRoutedEventArgs const& e); @@ -224,6 +225,8 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation void _Search(const winrt::hstring& text, const bool goForward, const bool caseSensitive); void _CloseSearchBoxControl(const winrt::Windows::Foundation::IInspectable& sender, Windows::UI::Xaml::RoutedEventArgs const& args); + + // TSFInputControl Handlers void _CompositionCompleted(winrt::hstring text); void _CurrentCursorPositionHandler(const IInspectable& sender, const CursorPositionEventArgs& eventArgs); diff --git a/src/cascadia/TerminalControl/TerminalControl.vcxproj b/src/cascadia/TerminalControl/TerminalControl.vcxproj index 99fffe0770f..149e920f4ba 100644 --- a/src/cascadia/TerminalControl/TerminalControl.vcxproj +++ b/src/cascadia/TerminalControl/TerminalControl.vcxproj @@ -76,6 +76,7 @@ TermControl.xaml + TSFInputControl.xaml diff --git a/src/cascadia/WindowsTerminal/AppHost.cpp b/src/cascadia/WindowsTerminal/AppHost.cpp index f1736b23563..fa56a1758a2 100644 --- a/src/cascadia/WindowsTerminal/AppHost.cpp +++ b/src/cascadia/WindowsTerminal/AppHost.cpp @@ -340,7 +340,7 @@ void AppHost::_ToggleFullscreen(const winrt::Windows::Foundation::IInspectable&, _window->ToggleFullscreen(); } -void AppHost::_WindowMouseWheeled(const til::point coord, const bool isHorizontalScroll, const float delta) +void AppHost::_WindowMouseWheeled(const til::point coord, const bool isHorizontalScroll, const int32_t delta) { isHorizontalScroll; delta; diff --git a/src/cascadia/WindowsTerminal/AppHost.h b/src/cascadia/WindowsTerminal/AppHost.h index 0cfcf7961a5..1e8dff76346 100644 --- a/src/cascadia/WindowsTerminal/AppHost.h +++ b/src/cascadia/WindowsTerminal/AppHost.h @@ -35,5 +35,5 @@ class AppHost const winrt::Windows::UI::Xaml::ElementTheme& arg); void _ToggleFullscreen(const winrt::Windows::Foundation::IInspectable& sender, const winrt::TerminalApp::ToggleFullscreenEventArgs& arg); - void _WindowMouseWheeled(const til::point coord, const bool isHorizontalScroll, const float delta); + void _WindowMouseWheeled(const til::point coord, const bool isHorizontalScroll, const int32_t delta); }; diff --git a/src/cascadia/WindowsTerminal/IslandWindow.cpp b/src/cascadia/WindowsTerminal/IslandWindow.cpp index d24bebf3521..daff09ae33c 100644 --- a/src/cascadia/WindowsTerminal/IslandWindow.cpp +++ b/src/cascadia/WindowsTerminal/IslandWindow.cpp @@ -359,7 +359,13 @@ BOOL CALLBACK okay(HWND child, LPARAM lp) auto relative = eventPoint-origin; auto x1 = gsl::narrow_cast(relative.x() / GetCurrentDpiScale()); auto y1 = gsl::narrow_cast(relative.y() / GetCurrentDpiScale()); + + auto x2 = gsl::narrow_cast(relative.x() / GetCurrentDpiScale()); + auto y2 = gsl::narrow_cast(relative.y() / GetCurrentDpiScale()); + auto real = til::point{ x1, y1 }; + auto real2 = til::point{ x2, y2 }; + real2; short wheelDelta = (short)HIWORD(wparam); diff --git a/src/cascadia/WindowsTerminal/IslandWindow.h b/src/cascadia/WindowsTerminal/IslandWindow.h index 02a68b2c923..1b673ea44ea 100644 --- a/src/cascadia/WindowsTerminal/IslandWindow.h +++ b/src/cascadia/WindowsTerminal/IslandWindow.h @@ -72,7 +72,7 @@ class IslandWindow : DECLARE_EVENT(DragRegionClicked, _DragRegionClickedHandlers, winrt::delegate<>); DECLARE_EVENT(WindowCloseButtonClicked, _windowCloseButtonClickedHandler, winrt::delegate<>); - WINRT_CALLBACK(MouseScrolled, winrt::delegate); + WINRT_CALLBACK(MouseScrolled, winrt::delegate); protected: void ForceResize() From cf9d17282474c4bc6098566a183eff1f3b8f1115 Mon Sep 17 00:00:00 2001 From: zadjii-msft Date: Wed, 25 Mar 2020 10:43:32 -0500 Subject: [PATCH 07/18] So very much code cleanup Also for good measure, let's link this to #979 --- .../TerminalControl/IMouseWheelListener.idl | 6 +- src/cascadia/TerminalControl/TermControl.cpp | 67 ++++++++++++++----- src/cascadia/TerminalControl/TermControl.h | 6 +- src/cascadia/WindowsTerminal/AppHost.cpp | 51 +++++++------- src/cascadia/WindowsTerminal/AppHost.h | 2 +- src/cascadia/WindowsTerminal/IslandWindow.cpp | 49 +++++++------- src/cascadia/WindowsTerminal/IslandWindow.h | 2 +- src/inc/til/point.h | 44 ++++++++++++ src/til/ut_til/PointTests.cpp | 63 +++++++++++++++++ 9 files changed, 215 insertions(+), 75 deletions(-) diff --git a/src/cascadia/TerminalControl/IMouseWheelListener.idl b/src/cascadia/TerminalControl/IMouseWheelListener.idl index 2ac937da6eb..63089552683 100644 --- a/src/cascadia/TerminalControl/IMouseWheelListener.idl +++ b/src/cascadia/TerminalControl/IMouseWheelListener.idl @@ -3,10 +3,14 @@ namespace Microsoft.Terminal.TerminalControl { + + // This interface is a hack for GH#979. Controls should implement this + // interface to be able to be notified of mousewheel events even on devices + // who's trackpads won't scroll inactive windows. + [uuid("65b8b8c5-988f-43ff-aba9-e89368da1598")] interface IMouseWheelListener { Boolean OnMouseWheel(Windows.Foundation.Point coord, Int32 delta); - Boolean OnMouseHWheel(Windows.Foundation.Point coord, Int32 delta); } } diff --git a/src/cascadia/TerminalControl/TermControl.cpp b/src/cascadia/TerminalControl/TermControl.cpp index 25fd1557326..d079ee809e5 100644 --- a/src/cascadia/TerminalControl/TermControl.cpp +++ b/src/cascadia/TerminalControl/TermControl.cpp @@ -1154,25 +1154,44 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation // - Event handler for the PointerWheelChanged event. This is raised in // response to mouse wheel changes. Depending upon what modifier keys are // pressed, different actions will take place. + // - Primarily just takes the data from the PointerRoutedEventArgs and uses + // it to call _DoMouseWheel, see _DoMouseWheel for more details. // Arguments: // - args: the event args containing information about t`he mouse wheel event. void TermControl::_MouseWheelHandler(Windows::Foundation::IInspectable const& /*sender*/, Input::PointerRoutedEventArgs const& args) { const auto point = args.GetCurrentPoint(*this); - auto result = _DoMouseWheel(point.Position(), static_cast(args.KeyModifiers()), point.Properties().MouseWheelDelta(), point.Properties().IsLeftButtonPressed()); + auto result = _DoMouseWheel(point.Position(), + args.KeyModifiers(), + point.Properties().MouseWheelDelta(), + point.Properties().IsLeftButtonPressed()); if (result) { args.Handled(true); } } - bool TermControl::_DoMouseWheel(const Windows::Foundation::Point point, const uint32_t modifiers, const int32_t delta, const bool isLeftButtonPressed) + // Method Description: + // - Actually handle a scrolling event, with from a mouse wheel or a touchpad scroll. Depending upon what modifier keys are + // pressed, different actions will take place. + // * Attempts to first dispatch the mouse scroll as a VT event + // * If Ctrl+Shift are pressed, then attempts to change our opacity + // * If just Ctrl is pressed, we'll attempt to "zoom" by changing our font size + // * Otherwise, just scrolls the content of the viewport + // Arguments: + // - point: the location of the mouse during this event + // - modifiers: The modifiers pressed during this event, in the form of a VirtualKeyModifiers + // - delta: the mouse wheel delta that triggered this event. + bool TermControl::_DoMouseWheel(const Windows::Foundation::Point point, + const VirtualKeyModifiers modifiers, + const int32_t delta, + const bool isLeftButtonPressed) { if (_CanSendVTMouseInput()) { - // GAH this used to be + // TODO this used to be // _TrySendMouseEvent(point); // But we don't have a PointerPoint anymore. So we're going to fake that this is only a mousewheel. const auto terminalPosition = _GetTerminalPosition(point); @@ -1183,8 +1202,10 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation // Get the state of the Ctrl & Shift keys // static_cast to a uint32_t because we can't use the WI_IsFlagSet macro // directly with a VirtualKeyModifiers - const auto ctrlPressed = WI_IsFlagSet(modifiers, static_cast(VirtualKeyModifiers::Control)); - const auto shiftPressed = WI_IsFlagSet(modifiers, static_cast(VirtualKeyModifiers::Shift)); + const auto ctrlPressed = WI_IsFlagSet(static_cast(modifiers), + static_cast(VirtualKeyModifiers::Control)); + const auto shiftPressed = WI_IsFlagSet(static_cast(modifiers), + static_cast(VirtualKeyModifiers::Shift)); if (ctrlPressed && shiftPressed) { @@ -1201,6 +1222,25 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation return false; } + + // Method Description: + // - This is part of the solution to GH#979 + // - Manually handle a scrolling event. This is used to help support + // scrolling on devices where the touchpad doesn't correctly handle + // scrolling inactive windows. + // Arguments: + // - location: the location of the mouse during this event + // - delta: the mouse wheel delta that triggered this event. + bool TermControl::OnMouseWheel(const Windows::Foundation::Point location, + const int32_t delta) + { + // TODO: Right now, the location is window-relative. I believe this needs to get converted to control-relative + + const auto modifiers = _GetPressedModifierKeys(); + // TODO: Try and use the above to get the current modifiers, instead of just None + return _DoMouseWheel(location, Windows::System::VirtualKeyModifiers::None, delta, false); + } + // Method Description: // - Adjust the opacity of the acrylic background in response to a mouse // scrolling event. @@ -1271,7 +1311,11 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation // - Scroll the visible viewport in response to a mouse wheel event. // Arguments: // - mouseDelta: the mouse wheel delta that triggered this event. - void TermControl::_MouseScrollHandler(const double mouseDelta, const Windows::Foundation::Point point, const bool isLeftButtonPressed) + // - point: the location of the mouse during this event + // - isLeftButtonPressed: true iff the left mouse button was pressed during this event. + void TermControl::_MouseScrollHandler(const double mouseDelta, + const Windows::Foundation::Point point, + const bool isLeftButtonPressed) { const auto currentOffset = ScrollBar().Value(); @@ -2372,17 +2416,6 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation e.DragUIOverride().IsGlyphVisible(false); } - - bool TermControl::OnMouseWheel(Windows::Foundation::Point location, int32_t delta) - { - // const auto modifiers = _GetPressedModifierKeys(); - return _DoMouseWheel(location, 0, delta, false); - } - bool TermControl::OnMouseHWheel(Windows::Foundation::Point /*location*/, int32_t /*delta*/) - { - return false; - } - // -------------------------------- WinRT Events --------------------------------- // Winrt events need a method for adding a callback to the event and removing the callback. // These macros will define them both for you. diff --git a/src/cascadia/TerminalControl/TermControl.h b/src/cascadia/TerminalControl/TermControl.h index df869682727..72a4abd6b5d 100644 --- a/src/cascadia/TerminalControl/TermControl.h +++ b/src/cascadia/TerminalControl/TermControl.h @@ -83,8 +83,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation bool OnF7Pressed(); - bool OnMouseWheel(Windows::Foundation::Point location, int32_t delta); - bool OnMouseHWheel(Windows::Foundation::Point location, int32_t delta); + bool OnMouseWheel(const Windows::Foundation::Point location, const int32_t delta); ~TermControl(); @@ -201,7 +200,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation void _MouseScrollHandler(const double mouseDelta, const Windows::Foundation::Point point, const bool isLeftButtonPressed); void _MouseZoomHandler(const double delta); void _MouseTransparencyHandler(const double delta); - bool _DoMouseWheel(const Windows::Foundation::Point point, const uint32_t modifiers, const int32_t delta, const bool isLeftButtonPressed); + bool _DoMouseWheel(const Windows::Foundation::Point point, const Windows::System::VirtualKeyModifiers modifiers, const int32_t delta, const bool isLeftButtonPressed); bool _CapturePointer(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::Input::PointerRoutedEventArgs const& e); bool _ReleasePointerCapture(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::Input::PointerRoutedEventArgs const& e); @@ -226,7 +225,6 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation void _CloseSearchBoxControl(const winrt::Windows::Foundation::IInspectable& sender, Windows::UI::Xaml::RoutedEventArgs const& args); - // TSFInputControl Handlers void _CompositionCompleted(winrt::hstring text); void _CurrentCursorPositionHandler(const IInspectable& sender, const CursorPositionEventArgs& eventArgs); diff --git a/src/cascadia/WindowsTerminal/AppHost.cpp b/src/cascadia/WindowsTerminal/AppHost.cpp index fa56a1758a2..2fe39d6d882 100644 --- a/src/cascadia/WindowsTerminal/AppHost.cpp +++ b/src/cascadia/WindowsTerminal/AppHost.cpp @@ -340,37 +340,36 @@ void AppHost::_ToggleFullscreen(const winrt::Windows::Foundation::IInspectable&, _window->ToggleFullscreen(); } -void AppHost::_WindowMouseWheeled(const til::point coord, const bool isHorizontalScroll, const int32_t delta) +// Method Description: +// - Called when the IslandWindow has recieved a WM_MOUSEWHEEL message. This can +// happen oOn some laptops, where their trackpads won't scroll inactive windows +// _ever_. +// - We're going to take that message and manually plumb it through to our +// TermControl's, or anything else that implements IMouseWheelListener. +// - See GH#979 for more details. +// Arguments: +// - coord: The Window-relative, logical coordinates location of the mouse during this event. +// - delta: the wheel delta that triggered this event. +// Return Value: +// - +void AppHost::_WindowMouseWheeled(const til::point coord, const int32_t delta) { - isHorizontalScroll; - delta; - // winrt::Windows::UI::Xaml::Media::VisualTreeHelper::FindElementsInHostCoordinates - winrt::guid foo; - GUID bar; - bar = foo; - // winrt::Windows::Foundation::Point p{ coord }; - // coord.x - auto elems = winrt::Windows::UI::Xaml::Media::VisualTreeHelper::FindElementsInHostCoordinates(coord, _logic.GetRoot()); - for (const auto& e : elems) + if (_logic) { - auto control = e.try_as(); - if (control) + // Find all the elements that are underneath the mouse + auto elems = winrt::Windows::UI::Xaml::Media::VisualTreeHelper::FindElementsInHostCoordinates(coord, _logic.GetRoot()); + for (const auto& e : elems) { - control.OnMouseWheel(coord, delta); - if (isHorizontalScroll) + // If that element has implemented IMouseWheelListener, call OnMouseWheel on that element. + if (auto control{ e.try_as() }) { - control.OnMouseHWheel(coord, delta); - } - else - { - control.OnMouseWheel(coord, delta); + if (control.OnMouseWheel(coord, delta)) + { + // If the element handled the mouse wheel event, don't + // continue to iterate over the remaining controls. + break; + } } } } - - - - // auto root = _logic.GetRoot(); - // root. - // root.as(); } diff --git a/src/cascadia/WindowsTerminal/AppHost.h b/src/cascadia/WindowsTerminal/AppHost.h index 1e8dff76346..67f64b6e629 100644 --- a/src/cascadia/WindowsTerminal/AppHost.h +++ b/src/cascadia/WindowsTerminal/AppHost.h @@ -35,5 +35,5 @@ class AppHost const winrt::Windows::UI::Xaml::ElementTheme& arg); void _ToggleFullscreen(const winrt::Windows::Foundation::IInspectable& sender, const winrt::TerminalApp::ToggleFullscreenEventArgs& arg); - void _WindowMouseWheeled(const til::point coord, const bool isHorizontalScroll, const int32_t delta); + void _WindowMouseWheeled(const til::point coord, const int32_t delta); }; diff --git a/src/cascadia/WindowsTerminal/IslandWindow.cpp b/src/cascadia/WindowsTerminal/IslandWindow.cpp index daff09ae33c..594f4084246 100644 --- a/src/cascadia/WindowsTerminal/IslandWindow.cpp +++ b/src/cascadia/WindowsTerminal/IslandWindow.cpp @@ -342,37 +342,36 @@ BOOL CALLBACK okay(HWND child, LPARAM lp) return 0; } case WM_MOUSEWHEEL: - case WM_MOUSEHWHEEL: { - bool isMouseHWheel = message == WM_MOUSEHWHEEL; + // This whole handler is a hack for GH#979. + // + // On some laptops, their trackpads won't scroll inactive windows + // _ever_. With our entire window just being one giant XAML Island, the + // touchpad driver thinks our entire window is inactive, and won't + // scroll the XAML island. On those types of laptops, we'll get a + // WM_MOUSEWHEEL here, in our root window, when the trackpad scrolls. + // We're going to take that message and manually plumb it through to our + // TermControl's, or anything else that implements IMouseWheelListener. + // https://msdn.microsoft.com/en-us/library/windows/desktop/ms645617(v=vs.85).aspx - // Important Do not use the LOWORD or HIWORD macros to extract the x- and y- - // coordinates of the cursor position because these macros return incorrect - // results on systems with multiple monitors. Systems with multiple monitors - // can have negative x- and y- coordinates, and LOWORD and HIWORD treat the - // coordinates as unsigned quantities. - short x = GET_X_LPARAM(lparam); - short y = GET_Y_LPARAM(lparam); - const til::point eventPoint{x, y}; - const til::rectangle windowRect{GetWindowRect()}; + // Important! Do not use the LOWORD or HIWORD macros to extract the x- + // and y- coordinates of the cursor position because these macros return + // incorrect results on systems with multiple monitors. Systems with + // multiple monitors can have negative x- and y- coordinates, and LOWORD + // and HIWORD treat the coordinates as unsigned quantities. + const til::point eventPoint{GET_X_LPARAM(lparam), GET_Y_LPARAM(lparam)}; + // This mouse event is relative to the display origin, not the window. Convert here. + const til::rectangle windowRect{ GetWindowRect() }; const auto origin = windowRect.origin(); - auto relative = eventPoint-origin; - auto x1 = gsl::narrow_cast(relative.x() / GetCurrentDpiScale()); - auto y1 = gsl::narrow_cast(relative.y() / GetCurrentDpiScale()); - - auto x2 = gsl::narrow_cast(relative.x() / GetCurrentDpiScale()); - auto y2 = gsl::narrow_cast(relative.y() / GetCurrentDpiScale()); - - auto real = til::point{ x1, y1 }; - auto real2 = til::point{ x2, y2 }; - real2; + const auto relative = eventPoint - origin; + // Convert to logical scaling before raising the event. + const auto real = relative / GetCurrentDpiScale(); - short wheelDelta = (short)HIWORD(wparam); + const short wheelDelta = static_cast(HIWORD(wparam)); - _MouseScrolledHandlers(real, isMouseHWheel, wheelDelta); + // Raise an event, so any listeners can handle the mouse wheel event manually. + _MouseScrolledHandlers(real, wheelDelta); return 0; - break; - } } diff --git a/src/cascadia/WindowsTerminal/IslandWindow.h b/src/cascadia/WindowsTerminal/IslandWindow.h index 1b673ea44ea..4e3c96aeb14 100644 --- a/src/cascadia/WindowsTerminal/IslandWindow.h +++ b/src/cascadia/WindowsTerminal/IslandWindow.h @@ -72,7 +72,7 @@ class IslandWindow : DECLARE_EVENT(DragRegionClicked, _DragRegionClickedHandlers, winrt::delegate<>); DECLARE_EVENT(WindowCloseButtonClicked, _windowCloseButtonClickedHandler, winrt::delegate<>); - WINRT_CALLBACK(MouseScrolled, winrt::delegate); + WINRT_CALLBACK(MouseScrolled, winrt::delegate); protected: void ForceResize() diff --git a/src/inc/til/point.h b/src/inc/til/point.h index 52f25b578c5..f99bba1f12e 100644 --- a/src/inc/til/point.h +++ b/src/inc/til/point.h @@ -140,6 +140,50 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned" return point{ x, y }; } + point operator*(const int& scale) const + { + ptrdiff_t x; + THROW_HR_IF(E_ABORT, !base::CheckMul(_x, scale).AssignIfValid(&x)); + + ptrdiff_t y; + THROW_HR_IF(E_ABORT, !base::CheckMul(_y, scale).AssignIfValid(&y)); + + return point{ x, y }; + } + + point operator/(const int& scale) const + { + ptrdiff_t x; + THROW_HR_IF(E_ABORT, !base::CheckDiv(_x, scale).AssignIfValid(&x)); + + ptrdiff_t y; + THROW_HR_IF(E_ABORT, !base::CheckDiv(_y, scale).AssignIfValid(&y)); + + return point{ x, y }; + } + + point operator*(const float& scale) const + { + ptrdiff_t x; + THROW_HR_IF(E_ABORT, !base::CheckMul(_x, scale).AssignIfValid(&x)); + + ptrdiff_t y; + THROW_HR_IF(E_ABORT, !base::CheckMul(_y, scale).AssignIfValid(&y)); + + return point{ x, y }; + } + + point operator/(const float& scale) const + { + ptrdiff_t x; + THROW_HR_IF(E_ABORT, !base::CheckDiv(_x, scale).AssignIfValid(&x)); + + ptrdiff_t y; + THROW_HR_IF(E_ABORT, !base::CheckDiv(_y, scale).AssignIfValid(&y)); + + return point{ x, y }; + } + constexpr ptrdiff_t x() const noexcept { return _x; diff --git a/src/til/ut_til/PointTests.cpp b/src/til/ut_til/PointTests.cpp index 724d37ad7ef..64cb8a95858 100644 --- a/src/til/ut_til/PointTests.cpp +++ b/src/til/ut_til/PointTests.cpp @@ -443,4 +443,67 @@ class PointTests // All ptrdiff_ts fit into a float, so there's no exception tests. } + + + TEST_METHOD(Scaling) + { + Log::Comment(L"0.) Multiplication of two things that should be in bounds."); + { + const til::point pt{ 5, 10 }; + const int scale = 23 ; + + const til::point expected{ pt.x() * scale, pt.y() * scale }; + + VERIFY_ARE_EQUAL(expected, pt * scale); + } + + Log::Comment(L"1.) Multiplication results in value that is too large (x)."); + { + constexpr ptrdiff_t bigSize = std::numeric_limits().max(); + const til::point pt{ bigSize, static_cast(0) }; + const int scale = 10; + + auto fn = [&]() { + pt* scale; + }; + + VERIFY_THROWS_SPECIFIC(fn(), wil::ResultException, [](wil::ResultException& e) { return e.GetErrorCode() == E_ABORT; }); + } + + Log::Comment(L"2.) Multiplication results in value that is too large (y)."); + { + constexpr ptrdiff_t bigSize = std::numeric_limits().max(); + const til::point pt{ static_cast(0), bigSize }; + const int scale = 10; + + auto fn = [&]() { + pt* scale; + }; + + VERIFY_THROWS_SPECIFIC(fn(), wil::ResultException, [](wil::ResultException& e) { return e.GetErrorCode() == E_ABORT; }); + } + + Log::Comment(L"3.) Division of two things that should be in bounds."); + { + const til::point pt{ 555, 510 }; + const int scale = 23 ; + + const til::point expected{ pt.x() / scale, pt.y() / scale }; + + VERIFY_ARE_EQUAL(expected, pt / scale); + } + + Log::Comment(L"4.) Division by zero"); + { + constexpr ptrdiff_t bigSize = std::numeric_limits().max(); + const til::point pt{ 1, 1 }; + const int scale = 0; + + auto fn = [&]() { + pt / scale; + }; + + VERIFY_THROWS_SPECIFIC(fn(), wil::ResultException, [](wil::ResultException& e) { return e.GetErrorCode() == E_ABORT; }); + } + } }; From 47f859141244d8af4a00202cf2f3de4a5e6af580 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Thu, 26 Mar 2020 08:43:14 -0500 Subject: [PATCH 08/18] runformat --- src/cascadia/TerminalApp/TerminalPage.cpp | 2 +- src/cascadia/TerminalControl/TermControl.cpp | 4 +--- src/cascadia/TerminalControl/TermControl.h | 1 - src/cascadia/WindowsTerminal/AppHost.cpp | 3 +-- src/cascadia/WindowsTerminal/IslandWindow.cpp | 19 +------------------ src/til/ut_til/PointTests.cpp | 5 ++--- 6 files changed, 6 insertions(+), 28 deletions(-) diff --git a/src/cascadia/TerminalApp/TerminalPage.cpp b/src/cascadia/TerminalApp/TerminalPage.cpp index 221be5c0f89..0f2773402dd 100644 --- a/src/cascadia/TerminalApp/TerminalPage.cpp +++ b/src/cascadia/TerminalApp/TerminalPage.cpp @@ -665,7 +665,7 @@ namespace winrt::TerminalApp::implementation settings.InitialRows(), settings.InitialCols(), winrt::guid()); - sessionGuid = (GUID)conhostConn.Guid(); + sessionGuid = conhostConn.Guid(); connection = conhostConn; } diff --git a/src/cascadia/TerminalControl/TermControl.cpp b/src/cascadia/TerminalControl/TermControl.cpp index 1ce47982837..4f3d510ace7 100644 --- a/src/cascadia/TerminalControl/TermControl.cpp +++ b/src/cascadia/TerminalControl/TermControl.cpp @@ -1189,7 +1189,6 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation const int32_t delta, const bool isLeftButtonPressed) { - if (_CanSendVTMouseInput()) { // TODO this used to be @@ -1206,7 +1205,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation const auto ctrlPressed = WI_IsFlagSet(static_cast(modifiers), static_cast(VirtualKeyModifiers::Control)); const auto shiftPressed = WI_IsFlagSet(static_cast(modifiers), - static_cast(VirtualKeyModifiers::Shift)); + static_cast(VirtualKeyModifiers::Shift)); if (ctrlPressed && shiftPressed) { @@ -1223,7 +1222,6 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation return false; } - // Method Description: // - This is part of the solution to GH#979 // - Manually handle a scrolling event. This is used to help support diff --git a/src/cascadia/TerminalControl/TermControl.h b/src/cascadia/TerminalControl/TermControl.h index 5e2fec19e6b..26696dfe14a 100644 --- a/src/cascadia/TerminalControl/TermControl.h +++ b/src/cascadia/TerminalControl/TermControl.h @@ -227,7 +227,6 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation void _Search(const winrt::hstring& text, const bool goForward, const bool caseSensitive); void _CloseSearchBoxControl(const winrt::Windows::Foundation::IInspectable& sender, Windows::UI::Xaml::RoutedEventArgs const& args); - // TSFInputControl Handlers void _CompositionCompleted(winrt::hstring text); void _CurrentCursorPositionHandler(const IInspectable& sender, const CursorPositionEventArgs& eventArgs); diff --git a/src/cascadia/WindowsTerminal/AppHost.cpp b/src/cascadia/WindowsTerminal/AppHost.cpp index 2fe39d6d882..ff9a715c34f 100644 --- a/src/cascadia/WindowsTerminal/AppHost.cpp +++ b/src/cascadia/WindowsTerminal/AppHost.cpp @@ -17,7 +17,6 @@ using namespace winrt::Windows::Foundation::Numerics; using namespace ::Microsoft::Console; using namespace ::Microsoft::Console::Types; - AppHost::AppHost() noexcept : _app{}, _logic{ nullptr }, // don't make one, we're going to take a ref on app's @@ -52,7 +51,7 @@ AppHost::AppHost() noexcept : _logic, std::placeholders::_1, std::placeholders::_2)); - _window->MouseScrolled({ this, &AppHost::_WindowMouseWheeled}); + _window->MouseScrolled({ this, &AppHost::_WindowMouseWheeled }); _window->MakeWindow(); } diff --git a/src/cascadia/WindowsTerminal/IslandWindow.cpp b/src/cascadia/WindowsTerminal/IslandWindow.cpp index 594f4084246..f9cc1671f87 100644 --- a/src/cascadia/WindowsTerminal/IslandWindow.cpp +++ b/src/cascadia/WindowsTerminal/IslandWindow.cpp @@ -264,21 +264,6 @@ void IslandWindow::OnSize(const UINT width, const UINT height) } } -struct MyMsg { - UINT message; - WPARAM wparam; - LPARAM lparam; -}; - -BOOL CALLBACK okay(HWND child, LPARAM lp) -{ - MyMsg m = *((MyMsg*)lp); - PostMessage(child, m.message, m.wparam, m.lparam); - - return true; - -} - [[nodiscard]] LRESULT IslandWindow::MessageHandler(UINT const message, WPARAM const wparam, LPARAM const lparam) noexcept { switch (message) @@ -359,7 +344,7 @@ BOOL CALLBACK okay(HWND child, LPARAM lp) // incorrect results on systems with multiple monitors. Systems with // multiple monitors can have negative x- and y- coordinates, and LOWORD // and HIWORD treat the coordinates as unsigned quantities. - const til::point eventPoint{GET_X_LPARAM(lparam), GET_Y_LPARAM(lparam)}; + const til::point eventPoint{ GET_X_LPARAM(lparam), GET_Y_LPARAM(lparam) }; // This mouse event is relative to the display origin, not the window. Convert here. const til::rectangle windowRect{ GetWindowRect() }; const auto origin = windowRect.origin(); @@ -375,8 +360,6 @@ BOOL CALLBACK okay(HWND child, LPARAM lp) } } - - // TODO: handle messages here... return base_type::MessageHandler(message, wparam, lparam); } diff --git a/src/til/ut_til/PointTests.cpp b/src/til/ut_til/PointTests.cpp index 64cb8a95858..25a7c03553e 100644 --- a/src/til/ut_til/PointTests.cpp +++ b/src/til/ut_til/PointTests.cpp @@ -444,13 +444,12 @@ class PointTests // All ptrdiff_ts fit into a float, so there's no exception tests. } - TEST_METHOD(Scaling) { Log::Comment(L"0.) Multiplication of two things that should be in bounds."); { const til::point pt{ 5, 10 }; - const int scale = 23 ; + const int scale = 23; const til::point expected{ pt.x() * scale, pt.y() * scale }; @@ -486,7 +485,7 @@ class PointTests Log::Comment(L"3.) Division of two things that should be in bounds."); { const til::point pt{ 555, 510 }; - const int scale = 23 ; + const int scale = 23; const til::point expected{ pt.x() / scale, pt.y() / scale }; From 10cb1337e00bfc1f8af52ac154f3428b40f3f499 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Thu, 26 Mar 2020 09:06:49 -0500 Subject: [PATCH 09/18] Appease the spelling god? --- .github/actions/spell-check/whitelist/whitelist.txt | 3 +++ src/cascadia/WindowsTerminal/AppHost.cpp | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/actions/spell-check/whitelist/whitelist.txt b/.github/actions/spell-check/whitelist/whitelist.txt index e8ce38722b4..50ad7a185d7 100644 --- a/.github/actions/spell-check/whitelist/whitelist.txt +++ b/.github/actions/spell-check/whitelist/whitelist.txt @@ -1130,6 +1130,7 @@ IIo IList ime Imm +IMouse Impl implementingtextandtextrange inbox @@ -2418,6 +2419,7 @@ TOPDOWNDIB TOPLEFT TOPRIGHT tosign +touchpad tounicodeex towlower towupper @@ -2429,6 +2431,7 @@ tracelogging traceloggingprovider trackbar TRACKCOMPOSITION +trackpad trackpads transcoder transitioning diff --git a/src/cascadia/WindowsTerminal/AppHost.cpp b/src/cascadia/WindowsTerminal/AppHost.cpp index ff9a715c34f..687d3e1068e 100644 --- a/src/cascadia/WindowsTerminal/AppHost.cpp +++ b/src/cascadia/WindowsTerminal/AppHost.cpp @@ -340,8 +340,8 @@ void AppHost::_ToggleFullscreen(const winrt::Windows::Foundation::IInspectable&, } // Method Description: -// - Called when the IslandWindow has recieved a WM_MOUSEWHEEL message. This can -// happen oOn some laptops, where their trackpads won't scroll inactive windows +// - Called when the IslandWindow has received a WM_MOUSEWHEEL message. This can +// happen on some laptops, where their trackpads won't scroll inactive windows // _ever_. // - We're going to take that message and manually plumb it through to our // TermControl's, or anything else that implements IMouseWheelListener. From 52c94dcd66dd52b651079c9996fe3c375fc03416 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Thu, 26 Mar 2020 09:12:21 -0500 Subject: [PATCH 10/18] fix the SA build --- src/inc/til/point.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/inc/til/point.h b/src/inc/til/point.h index f99bba1f12e..35379f25008 100644 --- a/src/inc/til/point.h +++ b/src/inc/til/point.h @@ -238,7 +238,7 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned" #endif #ifdef WINRT_Windows_Foundation_H - operator winrt::Windows::Foundation::Point() const noexcept + operator winrt::Windows::Foundation::Point() const { winrt::Windows::Foundation::Point ret; THROW_HR_IF(E_ABORT, !base::MakeCheckedNum(_x).AssignIfValid(&ret.X)); From 6e33a0fe24ab246ed835325c54a71d1be7c5226d Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Fri, 27 Mar 2020 11:23:06 -0500 Subject: [PATCH 11/18] this wasn't that scary --- src/inc/til/point.h | 30 +++++------------------- src/til/ut_til/PointTests.cpp | 44 +++++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+), 24 deletions(-) diff --git a/src/inc/til/point.h b/src/inc/til/point.h index 35379f25008..0f6ae56e651 100644 --- a/src/inc/til/point.h +++ b/src/inc/til/point.h @@ -140,30 +140,10 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned" return point{ x, y }; } - point operator*(const int& scale) const - { - ptrdiff_t x; - THROW_HR_IF(E_ABORT, !base::CheckMul(_x, scale).AssignIfValid(&x)); - - ptrdiff_t y; - THROW_HR_IF(E_ABORT, !base::CheckMul(_y, scale).AssignIfValid(&y)); - - return point{ x, y }; - } - - point operator/(const int& scale) const - { - ptrdiff_t x; - THROW_HR_IF(E_ABORT, !base::CheckDiv(_x, scale).AssignIfValid(&x)); - - ptrdiff_t y; - THROW_HR_IF(E_ABORT, !base::CheckDiv(_y, scale).AssignIfValid(&y)); - - return point{ x, y }; - } - - point operator*(const float& scale) const + template + point operator*(const T& scale) const { + static_assert(std::is_arithmetic::value, "Type must be arithmetic"); ptrdiff_t x; THROW_HR_IF(E_ABORT, !base::CheckMul(_x, scale).AssignIfValid(&x)); @@ -173,8 +153,10 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned" return point{ x, y }; } - point operator/(const float& scale) const + template + point operator/(const T& scale) const { + static_assert(std::is_arithmetic::value, "Type must be arithmetic"); ptrdiff_t x; THROW_HR_IF(E_ABORT, !base::CheckDiv(_x, scale).AssignIfValid(&x)); diff --git a/src/til/ut_til/PointTests.cpp b/src/til/ut_til/PointTests.cpp index 25a7c03553e..0c206f8c698 100644 --- a/src/til/ut_til/PointTests.cpp +++ b/src/til/ut_til/PointTests.cpp @@ -504,5 +504,49 @@ class PointTests VERIFY_THROWS_SPECIFIC(fn(), wil::ResultException, [](wil::ResultException& e) { return e.GetErrorCode() == E_ABORT; }); } + + Log::Comment(L"5.) Multiplication of floats that should be in bounds."); + { + const til::point pt{ 3, 10 }; + const float scale = 5.5f; + + // 3 * 5.5 = 15.5, which we'll round to 15 + const til::point expected{ 16, 55 }; + + VERIFY_ARE_EQUAL(expected, pt * scale); + } + + Log::Comment(L"6.) Multiplication of doubles that should be in bounds."); + { + const til::point pt{ 3, 10 }; + const double scale = 5.5f; + + // 3 * 5.5 = 15.5, which we'll round to 15 + const til::point expected{ 16, 55 }; + + VERIFY_ARE_EQUAL(expected, pt * scale); + } + + Log::Comment(L"5.) Division of floats that should be in bounds."); + { + const til::point pt{ 15, 10 }; + const float scale = 2.0f; + + // 15 / 2 = 7.5, which we'll floor to 7 + const til::point expected{ 7, 5 }; + + VERIFY_ARE_EQUAL(expected, pt / scale); + } + + Log::Comment(L"6.) Division of doubles that should be in bounds."); + { + const til::point pt{ 15, 10 }; + const double scale = 2.0; + + // 15 / 2 = 7.5, which we'll floor to 7 + const til::point expected{ 7, 5 }; + + VERIFY_ARE_EQUAL(expected, pt / scale); + } } }; From c0ed7ea87aca7b4b7ffcff759200f5e31db99338 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Fri, 27 Mar 2020 12:16:11 -0500 Subject: [PATCH 12/18] this is a handy helper for converting between the two --- src/cascadia/TerminalControl/TermControl.cpp | 29 ++++++++++++------- src/cascadia/TerminalControl/TermControl.h | 2 +- src/cascadia/TerminalControl/pch.h | 1 + .../TerminalCore/ControlKeyStates.hpp | 20 +++++++++++++ 4 files changed, 40 insertions(+), 12 deletions(-) diff --git a/src/cascadia/TerminalControl/TermControl.cpp b/src/cascadia/TerminalControl/TermControl.cpp index 4f3d510ace7..510255b7855 100644 --- a/src/cascadia/TerminalControl/TermControl.cpp +++ b/src/cascadia/TerminalControl/TermControl.cpp @@ -892,6 +892,18 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation return _terminal->IsTrackingMouseInput(); } + // ControlKeyStates TermControl::s_TranslateVirtaulkeys(const Windows::System::VirtualKeyModifiers& modifiers) noexcept : + // _value(0) + // { + // // static_cast to a uint32_t because we can't use the WI_IsFlagSet + // // macro directly with a VirtualKeyModifiers + // const auto m = static_cast(modifiers); + // _value |= WI_IsFlagSet(m, static_cast(VirtualKeyModifiers::Shift)) ? SHIFT_PRESSED : 0; + // // Since we can't differentiate between the left & right versions of Ctrl & Alt in a VirtualKeyModifiers + // _value |= WI_IsFlagSet(m, static_cast(VirtualKeyModifiers::Menu)) ? LEFT_ALT_PRESSED : 0; + // _value |= WI_IsFlagSet(m, static_cast(VirtualKeyModifiers::Ctrl)) ? LEFT_CTRL_PRESSED : 0; + // } + // Method Description: // - handle a mouse click event. Begin selection process. // Arguments: @@ -1164,7 +1176,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation { const auto point = args.GetCurrentPoint(*this); auto result = _DoMouseWheel(point.Position(), - args.KeyModifiers(), + ControlKeyStates{ args.KeyModifiers() }, point.Properties().MouseWheelDelta(), point.Properties().IsLeftButtonPressed()); if (result) @@ -1185,7 +1197,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation // - modifiers: The modifiers pressed during this event, in the form of a VirtualKeyModifiers // - delta: the mouse wheel delta that triggered this event. bool TermControl::_DoMouseWheel(const Windows::Foundation::Point point, - const VirtualKeyModifiers modifiers, + const ControlKeyStates modifiers, const int32_t delta, const bool isLeftButtonPressed) { @@ -1199,13 +1211,8 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation return _terminal->SendMouseEvent(terminalPosition, uiButton, _GetPressedModifierKeys(), ::base::saturated_cast(delta)); } - // Get the state of the Ctrl & Shift keys - // static_cast to a uint32_t because we can't use the WI_IsFlagSet macro - // directly with a VirtualKeyModifiers - const auto ctrlPressed = WI_IsFlagSet(static_cast(modifiers), - static_cast(VirtualKeyModifiers::Control)); - const auto shiftPressed = WI_IsFlagSet(static_cast(modifiers), - static_cast(VirtualKeyModifiers::Shift)); + const auto ctrlPressed = modifiers.IsCtrlPressed(); + const auto shiftPressed = modifiers.IsShiftPressed(); if (ctrlPressed && shiftPressed) { @@ -1236,8 +1243,8 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation // TODO: Right now, the location is window-relative. I believe this needs to get converted to control-relative const auto modifiers = _GetPressedModifierKeys(); - // TODO: Try and use the above to get the current modifiers, instead of just None - return _DoMouseWheel(location, Windows::System::VirtualKeyModifiers::None, delta, false); + + return _DoMouseWheel(location, modifiers, delta, false); } // Method Description: diff --git a/src/cascadia/TerminalControl/TermControl.h b/src/cascadia/TerminalControl/TermControl.h index 26696dfe14a..9ab8188186d 100644 --- a/src/cascadia/TerminalControl/TermControl.h +++ b/src/cascadia/TerminalControl/TermControl.h @@ -203,7 +203,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation void _MouseScrollHandler(const double mouseDelta, const Windows::Foundation::Point point, const bool isLeftButtonPressed); void _MouseZoomHandler(const double delta); void _MouseTransparencyHandler(const double delta); - bool _DoMouseWheel(const Windows::Foundation::Point point, const Windows::System::VirtualKeyModifiers modifiers, const int32_t delta, const bool isLeftButtonPressed); + bool _DoMouseWheel(const Windows::Foundation::Point point, const ::Microsoft::Terminal::Core::ControlKeyStates modifiers, const int32_t delta, const bool isLeftButtonPressed); bool _CapturePointer(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::Input::PointerRoutedEventArgs const& e); bool _ReleasePointerCapture(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::Input::PointerRoutedEventArgs const& e); diff --git a/src/cascadia/TerminalControl/pch.h b/src/cascadia/TerminalControl/pch.h index a22bf8a71b8..340baf2a6a4 100644 --- a/src/cascadia/TerminalControl/pch.h +++ b/src/cascadia/TerminalControl/pch.h @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include diff --git a/src/cascadia/TerminalCore/ControlKeyStates.hpp b/src/cascadia/TerminalCore/ControlKeyStates.hpp index cdd9c2f260d..66b071067a7 100644 --- a/src/cascadia/TerminalCore/ControlKeyStates.hpp +++ b/src/cascadia/TerminalCore/ControlKeyStates.hpp @@ -47,6 +47,26 @@ class Microsoft::Terminal::Core::ControlKeyStates return *this; } +#ifdef WINRT_Windows_System_H + ControlKeyStates(const winrt::Windows::System::VirtualKeyModifiers& modifiers) noexcept + { + // static_cast to a uint32_t because we can't use the WI_IsFlagSet + // macro directly with a VirtualKeyModifiers + const auto m = static_cast(modifiers); + _value |= WI_IsFlagSet(m, static_cast(winrt::Windows::System::VirtualKeyModifiers::Shift)) ? + SHIFT_PRESSED : + 0; + + // Since we can't differentiate between the left & right versions of Ctrl & Alt in a VirtualKeyModifiers + _value |= WI_IsFlagSet(m, static_cast(winrt::Windows::System::VirtualKeyModifiers::Menu)) ? + LEFT_ALT_PRESSED : + 0; + _value |= WI_IsFlagSet(m, static_cast(winrt::Windows::System::VirtualKeyModifiers::Control)) ? + LEFT_CTRL_PRESSED : + 0; + } +#endif + constexpr DWORD Value() const noexcept { return _value; From f3483c2400bd1599156dc4e0b5fc3cdf79f5877c Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Fri, 27 Mar 2020 12:22:31 -0500 Subject: [PATCH 13/18] Some minor code cleanup to make things easier to read --- src/cascadia/TerminalControl/TermControl.cpp | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/cascadia/TerminalControl/TermControl.cpp b/src/cascadia/TerminalControl/TermControl.cpp index 510255b7855..538b11e6191 100644 --- a/src/cascadia/TerminalControl/TermControl.cpp +++ b/src/cascadia/TerminalControl/TermControl.cpp @@ -1186,8 +1186,9 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation } // Method Description: - // - Actually handle a scrolling event, with from a mouse wheel or a touchpad scroll. Depending upon what modifier keys are - // pressed, different actions will take place. + // - Actually handle a scrolling event, with from a mouse wheel or a + // touchpad scroll. Depending upon what modifier keys are pressed, + // different actions will take place. // * Attempts to first dispatch the mouse scroll as a VT event // * If Ctrl+Shift are pressed, then attempts to change our opacity // * If just Ctrl is pressed, we'll attempt to "zoom" by changing our font size @@ -1203,12 +1204,15 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation { if (_CanSendVTMouseInput()) { - // TODO this used to be - // _TrySendMouseEvent(point); - // But we don't have a PointerPoint anymore. So we're going to fake that this is only a mousewheel. - const auto terminalPosition = _GetTerminalPosition(point); - unsigned int uiButton = WM_MOUSEWHEEL; - return _terminal->SendMouseEvent(terminalPosition, uiButton, _GetPressedModifierKeys(), ::base::saturated_cast(delta)); + // Most mouse event handlers call + // _TrySendMouseEvent(point); + // here with a PointerPoint. However, as of #979, we don't have a + // PointerPoint to work with. So, we're just going to do a + // mousewheel event manually + return _terminal->SendMouseEvent(_GetTerminalPosition(point), + WM_MOUSEWHEEL, + _GetPressedModifierKeys(), + ::base::saturated_cast(delta)); } const auto ctrlPressed = modifiers.IsCtrlPressed(); From c7a1e77c05404907b5f06f69f2497fbf1c0c0be8 Mon Sep 17 00:00:00 2001 From: zadjii-msft Date: Fri, 27 Mar 2020 12:53:44 -0500 Subject: [PATCH 14/18] some last changes for making events relative to the control origin --- src/cascadia/TerminalControl/TermControl.cpp | 6 ++---- src/cascadia/WindowsTerminal/AppHost.cpp | 8 +++++++- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/cascadia/TerminalControl/TermControl.cpp b/src/cascadia/TerminalControl/TermControl.cpp index 538b11e6191..ec01af15c96 100644 --- a/src/cascadia/TerminalControl/TermControl.cpp +++ b/src/cascadia/TerminalControl/TermControl.cpp @@ -1239,15 +1239,13 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation // scrolling on devices where the touchpad doesn't correctly handle // scrolling inactive windows. // Arguments: - // - location: the location of the mouse during this event + // - location: the location of the mouse during this event. This location is + // relative to the origin of the control // - delta: the mouse wheel delta that triggered this event. bool TermControl::OnMouseWheel(const Windows::Foundation::Point location, const int32_t delta) { - // TODO: Right now, the location is window-relative. I believe this needs to get converted to control-relative - const auto modifiers = _GetPressedModifierKeys(); - return _DoMouseWheel(location, modifiers, delta, false); } diff --git a/src/cascadia/WindowsTerminal/AppHost.cpp b/src/cascadia/WindowsTerminal/AppHost.cpp index 687d3e1068e..c2f97ec0d12 100644 --- a/src/cascadia/WindowsTerminal/AppHost.cpp +++ b/src/cascadia/WindowsTerminal/AppHost.cpp @@ -362,7 +362,13 @@ void AppHost::_WindowMouseWheeled(const til::point coord, const int32_t delta) // If that element has implemented IMouseWheelListener, call OnMouseWheel on that element. if (auto control{ e.try_as() }) { - if (control.OnMouseWheel(coord, delta)) + // Translate the event to the coordinate space of the control + // we're attempting to dispatch it to + const auto transform = e.TransformToVisual(nullptr); + const auto controlOrigin = transform.TransformPoint(til::point{ 0, 0 }); + const til::point offsetPoint{ ::base::ClampSub(coord.x(), controlOrigin.X), ::base::ClampSub(coord.y(), controlOrigin.Y) }; + + if (control.OnMouseWheel(offsetPoint, delta)) { // If the element handled the mouse wheel event, don't // continue to iterate over the remaining controls. From 0de39a72311617144ae4026623628033145ea5fe Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Fri, 27 Mar 2020 12:57:18 -0500 Subject: [PATCH 15/18] good bot --- src/cascadia/TerminalControl/TermControl.cpp | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/cascadia/TerminalControl/TermControl.cpp b/src/cascadia/TerminalControl/TermControl.cpp index ec01af15c96..40dfaf8f2fe 100644 --- a/src/cascadia/TerminalControl/TermControl.cpp +++ b/src/cascadia/TerminalControl/TermControl.cpp @@ -892,18 +892,6 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation return _terminal->IsTrackingMouseInput(); } - // ControlKeyStates TermControl::s_TranslateVirtaulkeys(const Windows::System::VirtualKeyModifiers& modifiers) noexcept : - // _value(0) - // { - // // static_cast to a uint32_t because we can't use the WI_IsFlagSet - // // macro directly with a VirtualKeyModifiers - // const auto m = static_cast(modifiers); - // _value |= WI_IsFlagSet(m, static_cast(VirtualKeyModifiers::Shift)) ? SHIFT_PRESSED : 0; - // // Since we can't differentiate between the left & right versions of Ctrl & Alt in a VirtualKeyModifiers - // _value |= WI_IsFlagSet(m, static_cast(VirtualKeyModifiers::Menu)) ? LEFT_ALT_PRESSED : 0; - // _value |= WI_IsFlagSet(m, static_cast(VirtualKeyModifiers::Ctrl)) ? LEFT_CTRL_PRESSED : 0; - // } - // Method Description: // - handle a mouse click event. Begin selection process. // Arguments: From 8c3e2842547a1181acd8efc855da69803b9f12db Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Mon, 30 Mar 2020 16:48:22 -0500 Subject: [PATCH 16/18] Wrap these exceptions up --- src/cascadia/TerminalApp/ActionArgs.h | 2 +- src/cascadia/TerminalControl/TermControl.cpp | 2 +- .../TerminalCore/ControlKeyStates.hpp | 3 +- src/cascadia/WindowsTerminal/AppHost.cpp | 25 +++++--- src/cascadia/WindowsTerminal/IslandWindow.cpp | 64 ++++++++++--------- 5 files changed, 52 insertions(+), 44 deletions(-) diff --git a/src/cascadia/TerminalApp/ActionArgs.h b/src/cascadia/TerminalApp/ActionArgs.h index c1b2e93a3f9..46de1356793 100644 --- a/src/cascadia/TerminalApp/ActionArgs.h +++ b/src/cascadia/TerminalApp/ActionArgs.h @@ -345,7 +345,7 @@ namespace winrt::TerminalApp::implementation struct SplitPaneArgs : public SplitPaneArgsT { SplitPaneArgs() = default; - GETSET_PROPERTY(winrt::TerminalApp::SplitState, SplitStyle, winrt::TerminalApp::SplitState::None); + GETSET_PROPERTY(winrt::TerminalApp::SplitState, SplitStyle, winrt::TerminalApp::SplitState::Automatic); GETSET_PROPERTY(winrt::TerminalApp::NewTerminalArgs, TerminalArgs, nullptr); GETSET_PROPERTY(winrt::TerminalApp::SplitType, SplitMode, winrt::TerminalApp::SplitType::Manual); diff --git a/src/cascadia/TerminalControl/TermControl.cpp b/src/cascadia/TerminalControl/TermControl.cpp index febec19ca14..df2f8bf474b 100644 --- a/src/cascadia/TerminalControl/TermControl.cpp +++ b/src/cascadia/TerminalControl/TermControl.cpp @@ -1193,7 +1193,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation } // Method Description: - // - Actually handle a scrolling event, with from a mouse wheel or a + // - Actually handle a scrolling event, wether from a mouse wheel or a // touchpad scroll. Depending upon what modifier keys are pressed, // different actions will take place. // * Attempts to first dispatch the mouse scroll as a VT event diff --git a/src/cascadia/TerminalCore/ControlKeyStates.hpp b/src/cascadia/TerminalCore/ControlKeyStates.hpp index 66b071067a7..16d6daa02cb 100644 --- a/src/cascadia/TerminalCore/ControlKeyStates.hpp +++ b/src/cascadia/TerminalCore/ControlKeyStates.hpp @@ -48,7 +48,8 @@ class Microsoft::Terminal::Core::ControlKeyStates } #ifdef WINRT_Windows_System_H - ControlKeyStates(const winrt::Windows::System::VirtualKeyModifiers& modifiers) noexcept + ControlKeyStates(const winrt::Windows::System::VirtualKeyModifiers& modifiers) noexcept : + _value{ 0 } { // static_cast to a uint32_t because we can't use the WI_IsFlagSet // macro directly with a VirtualKeyModifiers diff --git a/src/cascadia/WindowsTerminal/AppHost.cpp b/src/cascadia/WindowsTerminal/AppHost.cpp index c2f97ec0d12..adf042ba22f 100644 --- a/src/cascadia/WindowsTerminal/AppHost.cpp +++ b/src/cascadia/WindowsTerminal/AppHost.cpp @@ -362,18 +362,23 @@ void AppHost::_WindowMouseWheeled(const til::point coord, const int32_t delta) // If that element has implemented IMouseWheelListener, call OnMouseWheel on that element. if (auto control{ e.try_as() }) { - // Translate the event to the coordinate space of the control - // we're attempting to dispatch it to - const auto transform = e.TransformToVisual(nullptr); - const auto controlOrigin = transform.TransformPoint(til::point{ 0, 0 }); - const til::point offsetPoint{ ::base::ClampSub(coord.x(), controlOrigin.X), ::base::ClampSub(coord.y(), controlOrigin.Y) }; - - if (control.OnMouseWheel(offsetPoint, delta)) + try { - // If the element handled the mouse wheel event, don't - // continue to iterate over the remaining controls. - break; + // Translate the event to the coordinate space of the control + // we're attempting to dispatch it to + const auto transform = e.TransformToVisual(nullptr); + const til::point controlOrigin{ til::math::flooring, transform.TransformPoint(til::point{ 0, 0 }) }; + + const til::point offsetPoint = coord - controlOrigin; + + if (control.OnMouseWheel(offsetPoint, delta)) + { + // If the element handled the mouse wheel event, don't + // continue to iterate over the remaining controls. + break; + } } + CATCH_LOG(); } } } diff --git a/src/cascadia/WindowsTerminal/IslandWindow.cpp b/src/cascadia/WindowsTerminal/IslandWindow.cpp index f9cc1671f87..69d5cf5bc94 100644 --- a/src/cascadia/WindowsTerminal/IslandWindow.cpp +++ b/src/cascadia/WindowsTerminal/IslandWindow.cpp @@ -327,37 +327,39 @@ void IslandWindow::OnSize(const UINT width, const UINT height) return 0; } case WM_MOUSEWHEEL: - { - // This whole handler is a hack for GH#979. - // - // On some laptops, their trackpads won't scroll inactive windows - // _ever_. With our entire window just being one giant XAML Island, the - // touchpad driver thinks our entire window is inactive, and won't - // scroll the XAML island. On those types of laptops, we'll get a - // WM_MOUSEWHEEL here, in our root window, when the trackpad scrolls. - // We're going to take that message and manually plumb it through to our - // TermControl's, or anything else that implements IMouseWheelListener. - - // https://msdn.microsoft.com/en-us/library/windows/desktop/ms645617(v=vs.85).aspx - // Important! Do not use the LOWORD or HIWORD macros to extract the x- - // and y- coordinates of the cursor position because these macros return - // incorrect results on systems with multiple monitors. Systems with - // multiple monitors can have negative x- and y- coordinates, and LOWORD - // and HIWORD treat the coordinates as unsigned quantities. - const til::point eventPoint{ GET_X_LPARAM(lparam), GET_Y_LPARAM(lparam) }; - // This mouse event is relative to the display origin, not the window. Convert here. - const til::rectangle windowRect{ GetWindowRect() }; - const auto origin = windowRect.origin(); - const auto relative = eventPoint - origin; - // Convert to logical scaling before raising the event. - const auto real = relative / GetCurrentDpiScale(); - - const short wheelDelta = static_cast(HIWORD(wparam)); - - // Raise an event, so any listeners can handle the mouse wheel event manually. - _MouseScrolledHandlers(real, wheelDelta); - return 0; - } + try + { + // This whole handler is a hack for GH#979. + // + // On some laptops, their trackpads won't scroll inactive windows + // _ever_. With our entire window just being one giant XAML Island, the + // touchpad driver thinks our entire window is inactive, and won't + // scroll the XAML island. On those types of laptops, we'll get a + // WM_MOUSEWHEEL here, in our root window, when the trackpad scrolls. + // We're going to take that message and manually plumb it through to our + // TermControl's, or anything else that implements IMouseWheelListener. + + // https://msdn.microsoft.com/en-us/library/windows/desktop/ms645617(v=vs.85).aspx + // Important! Do not use the LOWORD or HIWORD macros to extract the x- + // and y- coordinates of the cursor position because these macros return + // incorrect results on systems with multiple monitors. Systems with + // multiple monitors can have negative x- and y- coordinates, and LOWORD + // and HIWORD treat the coordinates as unsigned quantities. + const til::point eventPoint{ GET_X_LPARAM(lparam), GET_Y_LPARAM(lparam) }; + // This mouse event is relative to the display origin, not the window. Convert here. + const til::rectangle windowRect{ GetWindowRect() }; + const auto origin = windowRect.origin(); + const auto relative = eventPoint - origin; + // Convert to logical scaling before raising the event. + const auto real = relative / GetCurrentDpiScale(); + + const short wheelDelta = static_cast(HIWORD(wparam)); + + // Raise an event, so any listeners can handle the mouse wheel event manually. + _MouseScrolledHandlers(real, wheelDelta); + return 0; + } + CATCH_LOG(); } // TODO: handle messages here... From ff021e096300bcd0f6f2c3f6a5318893b03c1e42 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Mon, 30 Mar 2020 16:54:56 -0500 Subject: [PATCH 17/18] This wasn't supposed to be on this branch --- src/cascadia/TerminalApp/ActionArgs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cascadia/TerminalApp/ActionArgs.h b/src/cascadia/TerminalApp/ActionArgs.h index 46de1356793..c1b2e93a3f9 100644 --- a/src/cascadia/TerminalApp/ActionArgs.h +++ b/src/cascadia/TerminalApp/ActionArgs.h @@ -345,7 +345,7 @@ namespace winrt::TerminalApp::implementation struct SplitPaneArgs : public SplitPaneArgsT { SplitPaneArgs() = default; - GETSET_PROPERTY(winrt::TerminalApp::SplitState, SplitStyle, winrt::TerminalApp::SplitState::Automatic); + GETSET_PROPERTY(winrt::TerminalApp::SplitState, SplitStyle, winrt::TerminalApp::SplitState::None); GETSET_PROPERTY(winrt::TerminalApp::NewTerminalArgs, TerminalArgs, nullptr); GETSET_PROPERTY(winrt::TerminalApp::SplitType, SplitMode, winrt::TerminalApp::SplitType::Manual); From 10e7baaffaae8fa393939e792772685d6b9d1884 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Wed, 1 Apr 2020 11:13:58 -0500 Subject: [PATCH 18/18] Update src/cascadia/TerminalControl/TermControl.cpp Co-Authored-By: Michael Niksa --- src/cascadia/TerminalControl/TermControl.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/cascadia/TerminalControl/TermControl.cpp b/src/cascadia/TerminalControl/TermControl.cpp index df2f8bf474b..0d606752dc3 100644 --- a/src/cascadia/TerminalControl/TermControl.cpp +++ b/src/cascadia/TerminalControl/TermControl.cpp @@ -1193,7 +1193,8 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation } // Method Description: - // - Actually handle a scrolling event, wether from a mouse wheel or a + // - Actually handle a scrolling event, whether from a mouse wheel or a + // touchpad scroll. Depending upon what modifier keys are pressed, // different actions will take place. // * Attempts to first dispatch the mouse scroll as a VT event