From 7560ee338f0f9a1d11af187aa6fcc05f2601c8ce Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Thu, 8 Apr 2021 16:38:06 -0500 Subject: [PATCH 1/9] The _quake window starts in focus mode, on the top half the screen. --- src/cascadia/TerminalApp/AppLogic.cpp | 14 ++++++-- src/cascadia/TerminalApp/AppLogic.h | 1 + src/cascadia/TerminalApp/AppLogic.idl | 1 + src/cascadia/TerminalApp/TerminalPage.cpp | 9 +++-- src/cascadia/TerminalApp/TerminalPage.h | 1 + src/cascadia/TerminalApp/TerminalPage.idl | 1 + src/cascadia/WindowsTerminal/AppHost.cpp | 33 +++++++++++++------ src/cascadia/WindowsTerminal/IslandWindow.cpp | 10 ++++++ src/cascadia/WindowsTerminal/IslandWindow.h | 2 +- .../WindowsTerminal/NonClientIslandWindow.cpp | 19 +++++++++++ 10 files changed, 76 insertions(+), 15 deletions(-) diff --git a/src/cascadia/TerminalApp/AppLogic.cpp b/src/cascadia/TerminalApp/AppLogic.cpp index 7f55b5f6865..19ede362f98 100644 --- a/src/cascadia/TerminalApp/AppLogic.cpp +++ b/src/cascadia/TerminalApp/AppLogic.cpp @@ -286,11 +286,16 @@ namespace winrt::TerminalApp::implementation // that the window size is _first_ set up as something sensible, so // leaving fullscreen returns to a reasonable size. const auto launchMode = this->GetLaunchMode(); - if (launchMode == LaunchMode::FullscreenMode) + if (IsQuakeWindow()) + { + _root->ToggleFocusMode(); + } + else if (launchMode == LaunchMode::FullscreenMode) { _root->ToggleFullscreen(); } - else if (launchMode == LaunchMode::FocusMode || launchMode == LaunchMode::MaximizedFocusMode) + else if (launchMode == LaunchMode::FocusMode || + launchMode == LaunchMode::MaximizedFocusMode) { _root->ToggleFocusMode(); } @@ -1419,4 +1424,9 @@ namespace winrt::TerminalApp::implementation } } + bool AppLogic::IsQuakeWindow() const + { + return _root->IsQuakeWindow(); + } + } diff --git a/src/cascadia/TerminalApp/AppLogic.h b/src/cascadia/TerminalApp/AppLogic.h index b35b7232159..1a71f5c1a28 100644 --- a/src/cascadia/TerminalApp/AppLogic.h +++ b/src/cascadia/TerminalApp/AppLogic.h @@ -66,6 +66,7 @@ namespace winrt::TerminalApp::implementation void WindowName(const winrt::hstring& name); uint64_t WindowId(); void WindowId(const uint64_t& id); + bool IsQuakeWindow() const; Windows::Foundation::Size GetLaunchDimensions(uint32_t dpi); bool CenterOnLaunch(); diff --git a/src/cascadia/TerminalApp/AppLogic.idl b/src/cascadia/TerminalApp/AppLogic.idl index 19647928ddc..6313f5e765f 100644 --- a/src/cascadia/TerminalApp/AppLogic.idl +++ b/src/cascadia/TerminalApp/AppLogic.idl @@ -52,6 +52,7 @@ namespace TerminalApp String WindowName; UInt64 WindowId; void RenameFailed(); + Boolean IsQuakeWindow(); Windows.Foundation.Size GetLaunchDimensions(UInt32 dpi); Boolean CenterOnLaunch { get; }; diff --git a/src/cascadia/TerminalApp/TerminalPage.cpp b/src/cascadia/TerminalApp/TerminalPage.cpp index 7b7ed2972d5..cbeae8d2722 100644 --- a/src/cascadia/TerminalApp/TerminalPage.cpp +++ b/src/cascadia/TerminalApp/TerminalPage.cpp @@ -2049,7 +2049,7 @@ namespace winrt::TerminalApp::implementation // - void TerminalPage::ToggleFocusMode() { - _isInFocusMode = !_isInFocusMode; + _isInFocusMode = !_isInFocusMode || IsQuakeWindow(); _UpdateTabView(); _FocusModeChangedHandlers(*this, nullptr); } @@ -2260,7 +2260,7 @@ namespace winrt::TerminalApp::implementation bool TerminalPage::FocusMode() const { - return _isInFocusMode; + return _isInFocusMode || IsQuakeWindow(); } bool TerminalPage::Fullscreen() const @@ -2735,4 +2735,9 @@ namespace winrt::TerminalApp::implementation WindowRenamer().IsOpen(false); } } + + bool TerminalPage::IsQuakeWindow() const + { + return WindowName() == L"_quake"; + } } diff --git a/src/cascadia/TerminalApp/TerminalPage.h b/src/cascadia/TerminalApp/TerminalPage.h index 7d34f43a3fe..0a6c0f18475 100644 --- a/src/cascadia/TerminalApp/TerminalPage.h +++ b/src/cascadia/TerminalApp/TerminalPage.h @@ -107,6 +107,7 @@ namespace winrt::TerminalApp::implementation void WindowId(const uint64_t& value); winrt::hstring WindowIdForDisplay() const noexcept; winrt::hstring WindowNameForDisplay() const noexcept; + bool IsQuakeWindow() const; WINRT_CALLBACK(PropertyChanged, Windows::UI::Xaml::Data::PropertyChangedEventHandler); diff --git a/src/cascadia/TerminalApp/TerminalPage.idl b/src/cascadia/TerminalApp/TerminalPage.idl index bf665d91bb2..0fb382634f1 100644 --- a/src/cascadia/TerminalApp/TerminalPage.idl +++ b/src/cascadia/TerminalApp/TerminalPage.idl @@ -33,6 +33,7 @@ namespace TerminalApp String WindowNameForDisplay { get; }; String WindowIdForDisplay { get; }; void RenameFailed(); + Boolean IsQuakeWindow(); // We cannot use the default XAML APIs because we want to make sure // that there's only one application-global dialog visible at a time, diff --git a/src/cascadia/WindowsTerminal/AppHost.cpp b/src/cascadia/WindowsTerminal/AppHost.cpp index 6082ea45977..e837cf8fdfb 100644 --- a/src/cascadia/WindowsTerminal/AppHost.cpp +++ b/src/cascadia/WindowsTerminal/AppHost.cpp @@ -57,6 +57,8 @@ AppHost::AppHost() noexcept : _window = std::make_unique(); } + _window->IsQuakeWindow(_logic.IsQuakeWindow()); + // Tell the window to callback to us when it's about to handle a WM_CREATE auto pfn = std::bind(&AppHost::_HandleCreateWindow, this, @@ -383,25 +385,36 @@ void AppHost::_HandleCreateWindow(const HWND hwnd, RECT proposedRect, LaunchMode adjustedWidth = islandWidth + nonClientSize.cx; adjustedHeight = islandHeight + nonClientSize.cy; - const COORD dimensions{ Utils::ClampToShortMax(adjustedWidth, 1), - Utils::ClampToShortMax(adjustedHeight, 1) }; + COORD dimensions{ Utils::ClampToShortMax(adjustedWidth, 1), + Utils::ClampToShortMax(adjustedHeight, 1) }; + + // Find nearest monitor for the position that we've actually settled on + HMONITOR hMonNearest = MonitorFromRect(&proposedRect, MONITOR_DEFAULTTONEAREST); + MONITORINFO nearestMonitorInfo; + nearestMonitorInfo.cbSize = sizeof(MONITORINFO); + // Get monitor dimensions: + GetMonitorInfo(hMonNearest, &nearestMonitorInfo); + const COORD desktopDimensions{ gsl::narrow(nearestMonitorInfo.rcWork.right - nearestMonitorInfo.rcWork.left), + gsl::narrow(nearestMonitorInfo.rcWork.bottom - nearestMonitorInfo.rcWork.top) }; if (centerOnLaunch) { - // Find nearest monitor for the position that we've actually settled on - HMONITOR hMonNearest = MonitorFromRect(&proposedRect, MONITOR_DEFAULTTONEAREST); - MONITORINFO nearestMonitorInfo; - nearestMonitorInfo.cbSize = sizeof(MONITORINFO); - // Get monitor dimensions: - GetMonitorInfo(hMonNearest, &nearestMonitorInfo); - const COORD desktopDimensions{ gsl::narrow(nearestMonitorInfo.rcWork.right - nearestMonitorInfo.rcWork.left), - gsl::narrow(nearestMonitorInfo.rcWork.bottom - nearestMonitorInfo.rcWork.top) }; // Move our proposed location into the center of that specific monitor. proposedRect.left = nearestMonitorInfo.rcWork.left + ((desktopDimensions.X / 2) - (dimensions.X / 2)); proposedRect.top = nearestMonitorInfo.rcWork.top + ((desktopDimensions.Y / 2) - (dimensions.Y / 2)); } + + if (_logic.IsQuakeWindow()) + { + proposedRect.left = nearestMonitorInfo.rcWork.left; + proposedRect.top = nearestMonitorInfo.rcWork.top; + dimensions.X = desktopDimensions.X; + dimensions.Y = desktopDimensions.Y / 2; + launchMode = LaunchMode::FocusMode; + } + const COORD origin{ gsl::narrow(proposedRect.left), gsl::narrow(proposedRect.top) }; diff --git a/src/cascadia/WindowsTerminal/IslandWindow.cpp b/src/cascadia/WindowsTerminal/IslandWindow.cpp index 0850f7e08df..7aa7899b398 100644 --- a/src/cascadia/WindowsTerminal/IslandWindow.cpp +++ b/src/cascadia/WindowsTerminal/IslandWindow.cpp @@ -195,6 +195,16 @@ LRESULT IslandWindow::_OnSizing(const WPARAM wParam, const LPARAM lParam) auto clientHeight = winRect->bottom - winRect->top - nonClientSize.cy; + // TODO! How do we prevent resizing for The Alt+Space menu? This seemingly + // doesn't do anything. + + // if (_IsQuakeWindow && wParam != WMSZ_BOTTOM) + // { + // return true; + // } + + // TODO! is there a way to prevent _moving_ the window as well? + if (wParam != WMSZ_TOP && wParam != WMSZ_BOTTOM) { // If user has dragged anything but the top or bottom border (so e.g. left border, diff --git a/src/cascadia/WindowsTerminal/IslandWindow.h b/src/cascadia/WindowsTerminal/IslandWindow.h index f17b81c252e..3109ef1ef11 100644 --- a/src/cascadia/WindowsTerminal/IslandWindow.h +++ b/src/cascadia/WindowsTerminal/IslandWindow.h @@ -40,7 +40,7 @@ class IslandWindow : winrt::fire_and_forget SummonWindow(); -#pragma endregion + WINRT_PROPERTY(bool, IsQuakeWindow, false); DECLARE_EVENT(DragRegionClicked, _DragRegionClickedHandlers, winrt::delegate<>); DECLARE_EVENT(WindowCloseButtonClicked, _windowCloseButtonClickedHandler, winrt::delegate<>); diff --git a/src/cascadia/WindowsTerminal/NonClientIslandWindow.cpp b/src/cascadia/WindowsTerminal/NonClientIslandWindow.cpp index a5d5c4b5672..db0157dd5c4 100644 --- a/src/cascadia/WindowsTerminal/NonClientIslandWindow.cpp +++ b/src/cascadia/WindowsTerminal/NonClientIslandWindow.cpp @@ -532,6 +532,25 @@ int NonClientIslandWindow::_GetResizeHandleHeight() const noexcept const auto originalRet = DefWindowProc(_window.get(), WM_NCHITTEST, 0, lParam); if (originalRet != HTCLIENT) { + // If we're the quake window, supress resizing on any side except the + // bottom. + // TODO! This doesn't actually work on the top. I believe that's handled below. + // + // TODO! Make sure that this works for the IslandWindow as well. + if (IsQuakeWindow()) + { + switch (originalRet) + { + case HTBOTTOMRIGHT: + case HTRIGHT: + case HTTOPRIGHT: + case HTTOP: + case HTTOPLEFT: + case HTLEFT: + case HTBOTTOMLEFT: + return HTCLIENT; + } + } return originalRet; } From 8d9c1f121336aa3e066b0a68cd98f0f38b4d0446 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Thu, 8 Apr 2021 17:06:09 -0500 Subject: [PATCH 2/9] Prevent resizing the quake window --- src/cascadia/WindowsTerminal/IslandWindow.cpp | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/cascadia/WindowsTerminal/IslandWindow.cpp b/src/cascadia/WindowsTerminal/IslandWindow.cpp index 7aa7899b398..377e3b69de3 100644 --- a/src/cascadia/WindowsTerminal/IslandWindow.cpp +++ b/src/cascadia/WindowsTerminal/IslandWindow.cpp @@ -195,13 +195,15 @@ LRESULT IslandWindow::_OnSizing(const WPARAM wParam, const LPARAM lParam) auto clientHeight = winRect->bottom - winRect->top - nonClientSize.cy; - // TODO! How do we prevent resizing for The Alt+Space menu? This seemingly - // doesn't do anything. - - // if (_IsQuakeWindow && wParam != WMSZ_BOTTOM) - // { - // return true; - // } + // If we're the quake window, prevent resizing on all sides except the + // bottom. This also applies to resising with the Alt+Space menu + if (_IsQuakeWindow && wParam != WMSZ_BOTTOM) + { + // Stuff our current window size into the lParam, and return true. This + // will tell User32 to use our current dimensions to resize to. + ::GetWindowRect(_window.get(), winRect); + return true; + } // TODO! is there a way to prevent _moving_ the window as well? From 2db7fd5a4c8a4760de5a650208a88a24919024d6 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Fri, 9 Apr 2021 06:07:25 -0500 Subject: [PATCH 3/9] Prevent the window from being moved as well --- src/cascadia/WindowsTerminal/IslandWindow.cpp | 30 +++++++++++++++++-- src/cascadia/WindowsTerminal/IslandWindow.h | 1 + 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/src/cascadia/WindowsTerminal/IslandWindow.cpp b/src/cascadia/WindowsTerminal/IslandWindow.cpp index 377e3b69de3..4b6419ccd13 100644 --- a/src/cascadia/WindowsTerminal/IslandWindow.cpp +++ b/src/cascadia/WindowsTerminal/IslandWindow.cpp @@ -205,8 +205,6 @@ LRESULT IslandWindow::_OnSizing(const WPARAM wParam, const LPARAM lParam) return true; } - // TODO! is there a way to prevent _moving_ the window as well? - if (wParam != WMSZ_TOP && wParam != WMSZ_BOTTOM) { // If user has dragged anything but the top or bottom border (so e.g. left border, @@ -259,6 +257,30 @@ LRESULT IslandWindow::_OnSizing(const WPARAM wParam, const LPARAM lParam) return TRUE; } +// Method Description: +// - Handle the WM_MOVING message +// - If we're the quake window, then we don't want to be able to be moved. +// Immediately return our current window position, which will prevent us from +// being moved at all. +// Arguments: +// - lParam: a LPRECT with the proposed window position, that should be filled +// with the resultant position. +// Return Value: +// - true iff we handled this message. +LRESULT IslandWindow::_OnMoving(const WPARAM /*wParam*/, const LPARAM lParam) +{ + LPRECT winRect = reinterpret_cast(lParam); + // If we're the quake window, prevent moving the window + if (_IsQuakeWindow) + { + // Stuff our current window into the lParam, and return true. This + // will tell User32 to use our current position to move to. + ::GetWindowRect(_window.get(), winRect); + return true; + } + return false; +} + void IslandWindow::Initialize() { const bool initialized = (_interopWindowHandle != nullptr); @@ -417,6 +439,10 @@ long IslandWindow::_calculateTotalSize(const bool isWidth, const long clientSize { return _OnSizing(wparam, lparam); } + case WM_MOVING: + { + return _OnMoving(wparam, lparam); + } case WM_CLOSE: { // If the user wants to close the app by clicking 'X' button, diff --git a/src/cascadia/WindowsTerminal/IslandWindow.h b/src/cascadia/WindowsTerminal/IslandWindow.h index 3109ef1ef11..7b24f6f50a6 100644 --- a/src/cascadia/WindowsTerminal/IslandWindow.h +++ b/src/cascadia/WindowsTerminal/IslandWindow.h @@ -66,6 +66,7 @@ class IslandWindow : void _HandleCreateWindow(const WPARAM wParam, const LPARAM lParam) noexcept; [[nodiscard]] LRESULT _OnSizing(const WPARAM wParam, const LPARAM lParam); + [[nodiscard]] LRESULT _OnMoving(const WPARAM wParam, const LPARAM lParam); bool _borderless{ false }; bool _fullscreen{ false }; From 04a4249bf554e00290cc8aadae35fa6f48cc9eb0 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Fri, 9 Apr 2021 06:16:25 -0500 Subject: [PATCH 4/9] suppress the resize handle on the top --- src/cascadia/WindowsTerminal/NonClientIslandWindow.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/cascadia/WindowsTerminal/NonClientIslandWindow.cpp b/src/cascadia/WindowsTerminal/NonClientIslandWindow.cpp index db0157dd5c4..2e5ce5f2300 100644 --- a/src/cascadia/WindowsTerminal/NonClientIslandWindow.cpp +++ b/src/cascadia/WindowsTerminal/NonClientIslandWindow.cpp @@ -533,8 +533,8 @@ int NonClientIslandWindow::_GetResizeHandleHeight() const noexcept if (originalRet != HTCLIENT) { // If we're the quake window, supress resizing on any side except the - // bottom. - // TODO! This doesn't actually work on the top. I believe that's handled below. + // bottom. I don't believe that this actually works on the top. That's + // handled below. // // TODO! Make sure that this works for the IslandWindow as well. if (IsQuakeWindow()) @@ -570,7 +570,9 @@ int NonClientIslandWindow::_GetResizeHandleHeight() const noexcept // the top of the drag bar is used to resize the window if (!_isMaximized && isOnResizeBorder) { - return HTTOP; + // However, if we're the quake window, then just return HTCAPTION so we + // don't get a resize handle on the top. + return IsQuakeWindow() ? HTCAPTION : HTTOP; } return HTCAPTION; From 87c6c2da6d909e3aa31465027aec84e094f9026c Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Fri, 9 Apr 2021 07:18:16 -0500 Subject: [PATCH 5/9] Renaming a window to _quake will snap it into quake mode --- src/cascadia/TerminalApp/AppLogic.h | 1 + src/cascadia/TerminalApp/AppLogic.idl | 1 + src/cascadia/TerminalApp/TerminalPage.cpp | 25 +++++++-- src/cascadia/TerminalApp/TerminalPage.h | 3 ++ src/cascadia/TerminalApp/TerminalPage.idl | 1 + src/cascadia/WindowsTerminal/AppHost.cpp | 8 ++- src/cascadia/WindowsTerminal/AppHost.h | 3 ++ src/cascadia/WindowsTerminal/IslandWindow.cpp | 52 ++++++++++++++++++- src/cascadia/WindowsTerminal/IslandWindow.h | 6 ++- 9 files changed, 93 insertions(+), 7 deletions(-) diff --git a/src/cascadia/TerminalApp/AppLogic.h b/src/cascadia/TerminalApp/AppLogic.h index 1a71f5c1a28..1c7e6b91e21 100644 --- a/src/cascadia/TerminalApp/AppLogic.h +++ b/src/cascadia/TerminalApp/AppLogic.h @@ -159,6 +159,7 @@ namespace winrt::TerminalApp::implementation FORWARDED_TYPED_EVENT(SetTaskbarProgress, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable, _root, SetTaskbarProgress); FORWARDED_TYPED_EVENT(IdentifyWindowsRequested, Windows::Foundation::IInspectable, Windows::Foundation::IInspectable, _root, IdentifyWindowsRequested); FORWARDED_TYPED_EVENT(RenameWindowRequested, Windows::Foundation::IInspectable, winrt::TerminalApp::RenameWindowRequestedArgs, _root, RenameWindowRequested); + FORWARDED_TYPED_EVENT(IsQuakeWindowChanged, Windows::Foundation::IInspectable, Windows::Foundation::IInspectable, _root, IsQuakeWindowChanged); #ifdef UNIT_TESTING friend class TerminalAppLocalTests::CommandlineTest; diff --git a/src/cascadia/TerminalApp/AppLogic.idl b/src/cascadia/TerminalApp/AppLogic.idl index 6313f5e765f..6bbd2a5d1e4 100644 --- a/src/cascadia/TerminalApp/AppLogic.idl +++ b/src/cascadia/TerminalApp/AppLogic.idl @@ -86,5 +86,6 @@ namespace TerminalApp event Windows.Foundation.TypedEventHandler SetTaskbarProgress; event Windows.Foundation.TypedEventHandler IdentifyWindowsRequested; event Windows.Foundation.TypedEventHandler RenameWindowRequested; + event Windows.Foundation.TypedEventHandler IsQuakeWindowChanged; } } diff --git a/src/cascadia/TerminalApp/TerminalPage.cpp b/src/cascadia/TerminalApp/TerminalPage.cpp index cbeae8d2722..cb85f4a7b7b 100644 --- a/src/cascadia/TerminalApp/TerminalPage.cpp +++ b/src/cascadia/TerminalApp/TerminalPage.cpp @@ -2049,9 +2049,17 @@ namespace winrt::TerminalApp::implementation // - void TerminalPage::ToggleFocusMode() { - _isInFocusMode = !_isInFocusMode || IsQuakeWindow(); - _UpdateTabView(); - _FocusModeChangedHandlers(*this, nullptr); + _SetFocusMode(!_isInFocusMode); + } + + void TerminalPage::_SetFocusMode(const bool inFocusMode) + { + if (inFocusMode != FocusMode()) + { + _isInFocusMode = inFocusMode || IsQuakeWindow(); + _UpdateTabView(); + _FocusModeChangedHandlers(*this, nullptr); + } } // Method Description: @@ -2596,10 +2604,21 @@ namespace winrt::TerminalApp::implementation } void TerminalPage::WindowName(const winrt::hstring& value) { + const bool oldIsQuakeMode = IsQuakeWindow(); if (_WindowName != value) { _WindowName = value; _PropertyChangedHandlers(*this, WUX::Data::PropertyChangedEventArgs{ L"WindowNameForDisplay" }); + + // If we're entering quake mode, or leaving it + if (IsQuakeWindow() != oldIsQuakeMode) + { + // If we're entering QM from ~FM, then this will enter FM + // If we're entering QM from FM, then this will do nothing + // If we're leaving QM (we're already in FM), then this will do nothing + _SetFocusMode(_isInFocusMode); + _IsQuakeWindowChangedHandlers(*this, nullptr); + } } } diff --git a/src/cascadia/TerminalApp/TerminalPage.h b/src/cascadia/TerminalApp/TerminalPage.h index 0a6c0f18475..a918f9c4997 100644 --- a/src/cascadia/TerminalApp/TerminalPage.h +++ b/src/cascadia/TerminalApp/TerminalPage.h @@ -123,6 +123,7 @@ namespace winrt::TerminalApp::implementation TYPED_EVENT(Initialized, IInspectable, winrt::Windows::UI::Xaml::RoutedEventArgs); TYPED_EVENT(IdentifyWindowsRequested, IInspectable, IInspectable); TYPED_EVENT(RenameWindowRequested, Windows::Foundation::IInspectable, winrt::TerminalApp::RenameWindowRequestedArgs); + TYPED_EVENT(IsQuakeWindowChanged, IInspectable, IInspectable); private: friend struct TerminalPageT; // for Xaml to bind events @@ -331,6 +332,8 @@ namespace winrt::TerminalApp::implementation void _UpdateTeachingTipTheme(winrt::Windows::UI::Xaml::FrameworkElement element); + void _SetFocusMode(const bool inFocusMode); + #pragma region ActionHandlers // These are all defined in AppActionHandlers.cpp #define ON_ALL_ACTIONS(action) DECLARE_ACTION_HANDLER(action); diff --git a/src/cascadia/TerminalApp/TerminalPage.idl b/src/cascadia/TerminalApp/TerminalPage.idl index 0fb382634f1..f1c1e55fc15 100644 --- a/src/cascadia/TerminalApp/TerminalPage.idl +++ b/src/cascadia/TerminalApp/TerminalPage.idl @@ -55,5 +55,6 @@ namespace TerminalApp event Windows.Foundation.TypedEventHandler SetTaskbarProgress; event Windows.Foundation.TypedEventHandler IdentifyWindowsRequested; event Windows.Foundation.TypedEventHandler RenameWindowRequested; + event Windows.Foundation.TypedEventHandler IsQuakeWindowChanged; } } diff --git a/src/cascadia/WindowsTerminal/AppHost.cpp b/src/cascadia/WindowsTerminal/AppHost.cpp index e837cf8fdfb..3deaa9107c2 100644 --- a/src/cascadia/WindowsTerminal/AppHost.cpp +++ b/src/cascadia/WindowsTerminal/AppHost.cpp @@ -244,7 +244,6 @@ void AppHost::Initialize() _logic.FullscreenChanged({ this, &AppHost::_FullscreenChanged }); _logic.FocusModeChanged({ this, &AppHost::_FocusModeChanged }); _logic.AlwaysOnTopChanged({ this, &AppHost::_AlwaysOnTopChanged }); - _logic.RaiseVisualBell({ this, &AppHost::_RaiseVisualBell }); _logic.Create(); @@ -253,6 +252,7 @@ void AppHost::Initialize() _logic.SetTaskbarProgress({ this, &AppHost::SetTaskbarProgress }); _logic.IdentifyWindowsRequested({ this, &AppHost::_IdentifyWindowsRequested }); _logic.RenameWindowRequested({ this, &AppHost::_RenameWindowRequested }); + _logic.IsQuakeWindowChanged({ this, &AppHost::_IsQuakeWindowChanged }); _window->UpdateTitle(_logic.Title()); @@ -687,3 +687,9 @@ winrt::fire_and_forget AppHost::_RenameWindowRequested(const winrt::Windows::Fou } } } + +void AppHost::_IsQuakeWindowChanged(const winrt::Windows::Foundation::IInspectable&, + const winrt::Windows::Foundation::IInspectable&) +{ + _window->IsQuakeWindow(_logic.IsQuakeWindow()); +} diff --git a/src/cascadia/WindowsTerminal/AppHost.h b/src/cascadia/WindowsTerminal/AppHost.h index a3a22603adb..3c32af7190a 100644 --- a/src/cascadia/WindowsTerminal/AppHost.h +++ b/src/cascadia/WindowsTerminal/AppHost.h @@ -59,4 +59,7 @@ class AppHost const winrt::TerminalApp::RenameWindowRequestedArgs args); GUID _CurrentDesktopGuid(); + + void _IsQuakeWindowChanged(const winrt::Windows::Foundation::IInspectable& sender, + const winrt::Windows::Foundation::IInspectable& args); }; diff --git a/src/cascadia/WindowsTerminal/IslandWindow.cpp b/src/cascadia/WindowsTerminal/IslandWindow.cpp index 4b6419ccd13..2a4ad606c1d 100644 --- a/src/cascadia/WindowsTerminal/IslandWindow.cpp +++ b/src/cascadia/WindowsTerminal/IslandWindow.cpp @@ -197,7 +197,7 @@ LRESULT IslandWindow::_OnSizing(const WPARAM wParam, const LPARAM lParam) // If we're the quake window, prevent resizing on all sides except the // bottom. This also applies to resising with the Alt+Space menu - if (_IsQuakeWindow && wParam != WMSZ_BOTTOM) + if (IsQuakeWindow() && wParam != WMSZ_BOTTOM) { // Stuff our current window size into the lParam, and return true. This // will tell User32 to use our current dimensions to resize to. @@ -271,7 +271,7 @@ LRESULT IslandWindow::_OnMoving(const WPARAM /*wParam*/, const LPARAM lParam) { LPRECT winRect = reinterpret_cast(lParam); // If we're the quake window, prevent moving the window - if (_IsQuakeWindow) + if (IsQuakeWindow()) { // Stuff our current window into the lParam, and return true. This // will tell User32 to use our current position to move to. @@ -787,6 +787,7 @@ void IslandWindow::_SetIsBorderless(const bool borderlessEnabled) // Resize the window, with SWP_FRAMECHANGED, to trigger user32 to // recalculate the non/client areas const til::rectangle windowPos{ GetWindowRect() }; + SetWindowPos(GetHandle(), HWND_TOP, windowPos.left(), @@ -918,5 +919,52 @@ winrt::fire_and_forget IslandWindow::SummonWindow() LOG_IF_WIN32_BOOL_FALSE(ShowWindow(_window.get(), SW_SHOW)); } +bool IslandWindow::IsQuakeWindow() const noexcept +{ + return _isQuakeWindow; +} + +void IslandWindow::IsQuakeWindow(bool isQuakeWindow) noexcept +{ + if (_isQuakeWindow != isQuakeWindow) + { + _isQuakeWindow = isQuakeWindow; + if (IsQuakeWindow()) + { + _enterQuakeMode(); + } + } +} + +void IslandWindow::_enterQuakeMode() +{ + RECT windowRect = GetWindowRect(); + HMONITOR hmon = MonitorFromRect(&windowRect, MONITOR_DEFAULTTONEAREST); + MONITORINFO nearestMonitorInfo; + nearestMonitorInfo.cbSize = sizeof(MONITORINFO); + // Get monitor dimensions: + GetMonitorInfo(hmon, &nearestMonitorInfo); + const COORD desktopDimensions{ gsl::narrow(nearestMonitorInfo.rcWork.right - nearestMonitorInfo.rcWork.left), + gsl::narrow(nearestMonitorInfo.rcWork.bottom - nearestMonitorInfo.rcWork.top) }; + + const til::point origin{ + ::base::saturated_cast(nearestMonitorInfo.rcWork.left), + ::base::saturated_cast(nearestMonitorInfo.rcWork.top) + }; + const til::size dimensions{ + desktopDimensions.X, + desktopDimensions.Y / 2 + }; + + const til::rectangle newRect{ origin, dimensions }; + SetWindowPos(GetHandle(), + HWND_TOP, + newRect.left(), + newRect.top(), + newRect.width(), + newRect.height(), + SWP_SHOWWINDOW | SWP_FRAMECHANGED | SWP_NOACTIVATE); +} + DEFINE_EVENT(IslandWindow, DragRegionClicked, _DragRegionClickedHandlers, winrt::delegate<>); DEFINE_EVENT(IslandWindow, WindowCloseButtonClicked, _windowCloseButtonClickedHandler, winrt::delegate<>); diff --git a/src/cascadia/WindowsTerminal/IslandWindow.h b/src/cascadia/WindowsTerminal/IslandWindow.h index 7b24f6f50a6..abd7f755df8 100644 --- a/src/cascadia/WindowsTerminal/IslandWindow.h +++ b/src/cascadia/WindowsTerminal/IslandWindow.h @@ -40,7 +40,8 @@ class IslandWindow : winrt::fire_and_forget SummonWindow(); - WINRT_PROPERTY(bool, IsQuakeWindow, false); + bool IsQuakeWindow() const noexcept; + void IsQuakeWindow(bool isQuakeWindow) noexcept; DECLARE_EVENT(DragRegionClicked, _DragRegionClickedHandlers, winrt::delegate<>); DECLARE_EVENT(WindowCloseButtonClicked, _windowCloseButtonClickedHandler, winrt::delegate<>); @@ -86,6 +87,9 @@ class IslandWindow : void _OnGetMinMaxInfo(const WPARAM wParam, const LPARAM lParam); long _calculateTotalSize(const bool isWidth, const long clientSize, const long nonClientSize); + bool _isQuakeWindow{ false }; + void _enterQuakeMode(); + private: // This minimum width allows for width the tabs fit static constexpr long minimumWidth = 460L; From 34f0dfdaff641ff740377d910f52ec9e54f85982 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Mon, 12 Apr 2021 07:02:10 -0500 Subject: [PATCH 6/9] Get rid of the margin on either side --- src/cascadia/TerminalApp/TabManagement.cpp | 17 ++++-- src/cascadia/WindowsTerminal/AppHost.cpp | 55 +++++++++++-------- src/cascadia/WindowsTerminal/IslandWindow.cpp | 21 +++++-- .../WindowsTerminal/NonClientIslandWindow.cpp | 2 - 4 files changed, 59 insertions(+), 36 deletions(-) diff --git a/src/cascadia/TerminalApp/TabManagement.cpp b/src/cascadia/TerminalApp/TabManagement.cpp index ee2d49aa468..b7282e2542a 100644 --- a/src/cascadia/TerminalApp/TabManagement.cpp +++ b/src/cascadia/TerminalApp/TabManagement.cpp @@ -272,12 +272,17 @@ namespace winrt::TerminalApp::implementation (_tabs.Size() > 1) || _settings.GlobalSettings().AlwaysShowTabs()); - // collapse/show the tabs themselves - _tabView.Visibility(isVisible ? Visibility::Visible : Visibility::Collapsed); - - // collapse/show the row that the tabs are in. - // NaN is the special value XAML uses for "Auto" sizing. - _tabRow.Height(isVisible ? NAN : 0); + if (_tabView) + { + // collapse/show the tabs themselves + _tabView.Visibility(isVisible ? Visibility::Visible : Visibility::Collapsed); + } + if (_tabRow) + { + // collapse/show the row that the tabs are in. + // NaN is the special value XAML uses for "Auto" sizing. + _tabRow.Height(isVisible ? NAN : 0); + } } // Method Description: diff --git a/src/cascadia/WindowsTerminal/AppHost.cpp b/src/cascadia/WindowsTerminal/AppHost.cpp index 3deaa9107c2..c9c68a7d13b 100644 --- a/src/cascadia/WindowsTerminal/AppHost.cpp +++ b/src/cascadia/WindowsTerminal/AppHost.cpp @@ -381,12 +381,12 @@ void AppHost::_HandleCreateWindow(const HWND hwnd, RECT proposedRect, LaunchMode // Get the size of a window we'd need to host that client rect. This will // add the titlebar space. - const auto nonClientSize = _window->GetTotalNonClientExclusiveSize(dpix); - adjustedWidth = islandWidth + nonClientSize.cx; - adjustedHeight = islandHeight + nonClientSize.cy; + const til::size nonClientSize = _window->GetTotalNonClientExclusiveSize(dpix); + adjustedWidth = islandWidth + nonClientSize.width(); + adjustedHeight = islandHeight + nonClientSize.height(); - COORD dimensions{ Utils::ClampToShortMax(adjustedWidth, 1), - Utils::ClampToShortMax(adjustedHeight, 1) }; + til::size dimensions{ Utils::ClampToShortMax(adjustedWidth, 1), + Utils::ClampToShortMax(adjustedHeight, 1) }; // Find nearest monitor for the position that we've actually settled on HMONITOR hMonNearest = MonitorFromRect(&proposedRect, MONITOR_DEFAULTTONEAREST); @@ -394,37 +394,46 @@ void AppHost::_HandleCreateWindow(const HWND hwnd, RECT proposedRect, LaunchMode nearestMonitorInfo.cbSize = sizeof(MONITORINFO); // Get monitor dimensions: GetMonitorInfo(hMonNearest, &nearestMonitorInfo); - const COORD desktopDimensions{ gsl::narrow(nearestMonitorInfo.rcWork.right - nearestMonitorInfo.rcWork.left), - gsl::narrow(nearestMonitorInfo.rcWork.bottom - nearestMonitorInfo.rcWork.top) }; + const til::size desktopDimensions{ gsl::narrow(nearestMonitorInfo.rcWork.right - nearestMonitorInfo.rcWork.left), + gsl::narrow(nearestMonitorInfo.rcWork.bottom - nearestMonitorInfo.rcWork.top) }; + til::point origin{ ::base::saturated_cast(proposedRect.left), + ::base::saturated_cast(proposedRect.top) }; if (centerOnLaunch) { // Move our proposed location into the center of that specific monitor. - proposedRect.left = nearestMonitorInfo.rcWork.left + - ((desktopDimensions.X / 2) - (dimensions.X / 2)); - proposedRect.top = nearestMonitorInfo.rcWork.top + - ((desktopDimensions.Y / 2) - (dimensions.Y / 2)); + origin = til::point{ + nearestMonitorInfo.rcWork.left + ((desktopDimensions.width() / 2) - (dimensions.width() / 2)), + nearestMonitorInfo.rcWork.top + ((desktopDimensions.height() / 2) - (dimensions.height() / 2)) + }; } if (_logic.IsQuakeWindow()) { - proposedRect.left = nearestMonitorInfo.rcWork.left; - proposedRect.top = nearestMonitorInfo.rcWork.top; - dimensions.X = desktopDimensions.X; - dimensions.Y = desktopDimensions.Y / 2; + // If we just use rcWork by itself, we'll fail to account for the invisible + // space reserved for the resize handles. So retrieve that size here. + const til::size ncSize{ _window->GetTotalNonClientExclusiveSize(dpix) }; + const til::size availableSpace = desktopDimensions + nonClientSize; + + origin = til::point{ + nearestMonitorInfo.rcWork.left - (nonClientSize.width() / 2), + nearestMonitorInfo.rcWork.top + }; + dimensions = til::size{ + availableSpace.width(), + availableSpace.height() / 2 + }; launchMode = LaunchMode::FocusMode; } - const COORD origin{ gsl::narrow(proposedRect.left), - gsl::narrow(proposedRect.top) }; - - const auto newPos = Viewport::FromDimensions(origin, dimensions); + const til::rectangle newRect{ origin, dimensions }; + // const auto newPos = Viewport::FromDimensions(origin, dimensions); bool succeeded = SetWindowPos(hwnd, nullptr, - newPos.Left(), - newPos.Top(), - newPos.Width(), - newPos.Height(), + newRect.left(), + newRect.top(), + newRect.width(), + newRect.height(), SWP_NOACTIVATE | SWP_NOZORDER); // Refresh the dpi of HWND because the dpi where the window will launch may be different diff --git a/src/cascadia/WindowsTerminal/IslandWindow.cpp b/src/cascadia/WindowsTerminal/IslandWindow.cpp index 2a4ad606c1d..86ab385ed95 100644 --- a/src/cascadia/WindowsTerminal/IslandWindow.cpp +++ b/src/cascadia/WindowsTerminal/IslandWindow.cpp @@ -941,19 +941,30 @@ void IslandWindow::_enterQuakeMode() RECT windowRect = GetWindowRect(); HMONITOR hmon = MonitorFromRect(&windowRect, MONITOR_DEFAULTTONEAREST); MONITORINFO nearestMonitorInfo; + + UINT dpix = USER_DEFAULT_SCREEN_DPI; + UINT dpiy = USER_DEFAULT_SCREEN_DPI; + // If this fails, we'll use the default of 96. + GetDpiForMonitor(hmon, MDT_EFFECTIVE_DPI, &dpix, &dpiy); + nearestMonitorInfo.cbSize = sizeof(MONITORINFO); // Get monitor dimensions: GetMonitorInfo(hmon, &nearestMonitorInfo); - const COORD desktopDimensions{ gsl::narrow(nearestMonitorInfo.rcWork.right - nearestMonitorInfo.rcWork.left), - gsl::narrow(nearestMonitorInfo.rcWork.bottom - nearestMonitorInfo.rcWork.top) }; + const til::size desktopDimensions{ gsl::narrow(nearestMonitorInfo.rcWork.right - nearestMonitorInfo.rcWork.left), + gsl::narrow(nearestMonitorInfo.rcWork.bottom - nearestMonitorInfo.rcWork.top) }; + + // If we just use rcWork by itself, we'll fail to account for the invisible + // space reserved for the resize handles. So retrieve that size here. + const til::size ncSize{ GetTotalNonClientExclusiveSize(dpix) }; + const til::size availableSpace = desktopDimensions + ncSize; const til::point origin{ - ::base::saturated_cast(nearestMonitorInfo.rcWork.left), + ::base::saturated_cast(nearestMonitorInfo.rcWork.left - (ncSize.width() / 2)), ::base::saturated_cast(nearestMonitorInfo.rcWork.top) }; const til::size dimensions{ - desktopDimensions.X, - desktopDimensions.Y / 2 + availableSpace.width(), + availableSpace.height() / 2 }; const til::rectangle newRect{ origin, dimensions }; diff --git a/src/cascadia/WindowsTerminal/NonClientIslandWindow.cpp b/src/cascadia/WindowsTerminal/NonClientIslandWindow.cpp index 2e5ce5f2300..b45595ba245 100644 --- a/src/cascadia/WindowsTerminal/NonClientIslandWindow.cpp +++ b/src/cascadia/WindowsTerminal/NonClientIslandWindow.cpp @@ -535,8 +535,6 @@ int NonClientIslandWindow::_GetResizeHandleHeight() const noexcept // If we're the quake window, supress resizing on any side except the // bottom. I don't believe that this actually works on the top. That's // handled below. - // - // TODO! Make sure that this works for the IslandWindow as well. if (IsQuakeWindow()) { switch (originalRet) From 2a1b4688104d8183389e3064936218ccdd112bb1 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Thu, 15 Apr 2021 07:18:41 -0500 Subject: [PATCH 7/9] most of the PR feedback --- .github/actions/spelling/expect/expect.txt | 6 ++++ src/cascadia/TerminalApp/AppLogic.cpp | 2 +- src/cascadia/TerminalApp/AppLogic.h | 2 +- src/cascadia/TerminalApp/TerminalPage.cpp | 12 ++++--- src/cascadia/TerminalApp/TerminalPage.h | 2 +- src/cascadia/WindowsTerminal/AppHost.cpp | 25 ++++++++------- src/cascadia/WindowsTerminal/IslandWindow.cpp | 32 ++++++++++++------- .../WindowsTerminal/NonClientIslandWindow.cpp | 2 +- 8 files changed, 50 insertions(+), 33 deletions(-) diff --git a/.github/actions/spelling/expect/expect.txt b/.github/actions/spelling/expect/expect.txt index 9df6f871af0..a0c76df6d78 100644 --- a/.github/actions/spelling/expect/expect.txt +++ b/.github/actions/spelling/expect/expect.txt @@ -1025,14 +1025,20 @@ hsl hstr hstring hsv +HTBOTTOMLEFT +HTBOTTOMRIGHT HTCAPTION HTCLIENT +HTLEFT htm HTMAXBUTTON HTMINBUTTON html HTMLTo +HTRIGHT HTTOP +HTTOPLEFT +HTTOPRIGHT hu hungapp HVP diff --git a/src/cascadia/TerminalApp/AppLogic.cpp b/src/cascadia/TerminalApp/AppLogic.cpp index 19ede362f98..ee1706f8364 100644 --- a/src/cascadia/TerminalApp/AppLogic.cpp +++ b/src/cascadia/TerminalApp/AppLogic.cpp @@ -1424,7 +1424,7 @@ namespace winrt::TerminalApp::implementation } } - bool AppLogic::IsQuakeWindow() const + bool AppLogic::IsQuakeWindow() const noexcept { return _root->IsQuakeWindow(); } diff --git a/src/cascadia/TerminalApp/AppLogic.h b/src/cascadia/TerminalApp/AppLogic.h index 1c7e6b91e21..54c1a206944 100644 --- a/src/cascadia/TerminalApp/AppLogic.h +++ b/src/cascadia/TerminalApp/AppLogic.h @@ -66,7 +66,7 @@ namespace winrt::TerminalApp::implementation void WindowName(const winrt::hstring& name); uint64_t WindowId(); void WindowId(const uint64_t& id); - bool IsQuakeWindow() const; + bool IsQuakeWindow() const noexcept; Windows::Foundation::Size GetLaunchDimensions(uint32_t dpi); bool CenterOnLaunch(); diff --git a/src/cascadia/TerminalApp/TerminalPage.cpp b/src/cascadia/TerminalApp/TerminalPage.cpp index cb85f4a7b7b..9b5cc911657 100644 --- a/src/cascadia/TerminalApp/TerminalPage.cpp +++ b/src/cascadia/TerminalApp/TerminalPage.cpp @@ -42,6 +42,8 @@ namespace winrt using IInspectable = Windows::Foundation::IInspectable; } +static constexpr std::wstring_view QuakeWindowName{ L"_quake" }; + namespace winrt::TerminalApp::implementation { TerminalPage::TerminalPage() : @@ -2613,9 +2615,9 @@ namespace winrt::TerminalApp::implementation // If we're entering quake mode, or leaving it if (IsQuakeWindow() != oldIsQuakeMode) { - // If we're entering QM from ~FM, then this will enter FM - // If we're entering QM from FM, then this will do nothing - // If we're leaving QM (we're already in FM), then this will do nothing + // If we're entering Quake Mode from ~Focus Mode, then this will enter Focus Mode + // If we're entering Quake Mode from Focus Mode, then this will do nothing + // If we're leaving Quake Mode (we're already in Focus Mode), then this will do nothing _SetFocusMode(_isInFocusMode); _IsQuakeWindowChangedHandlers(*this, nullptr); } @@ -2755,8 +2757,8 @@ namespace winrt::TerminalApp::implementation } } - bool TerminalPage::IsQuakeWindow() const + bool TerminalPage::IsQuakeWindow() const noexcept { - return WindowName() == L"_quake"; + return WindowName() == QuakeWindowName; } } diff --git a/src/cascadia/TerminalApp/TerminalPage.h b/src/cascadia/TerminalApp/TerminalPage.h index a918f9c4997..f7ad54c8dc8 100644 --- a/src/cascadia/TerminalApp/TerminalPage.h +++ b/src/cascadia/TerminalApp/TerminalPage.h @@ -107,7 +107,7 @@ namespace winrt::TerminalApp::implementation void WindowId(const uint64_t& value); winrt::hstring WindowIdForDisplay() const noexcept; winrt::hstring WindowNameForDisplay() const noexcept; - bool IsQuakeWindow() const; + bool IsQuakeWindow() const noexcept; WINRT_CALLBACK(PropertyChanged, Windows::UI::Xaml::Data::PropertyChangedEventHandler); diff --git a/src/cascadia/WindowsTerminal/AppHost.cpp b/src/cascadia/WindowsTerminal/AppHost.cpp index c9c68a7d13b..876b50bba82 100644 --- a/src/cascadia/WindowsTerminal/AppHost.cpp +++ b/src/cascadia/WindowsTerminal/AppHost.cpp @@ -57,7 +57,8 @@ AppHost::AppHost() noexcept : _window = std::make_unique(); } - _window->IsQuakeWindow(_logic.IsQuakeWindow()); + // Update our own internal state tracking if we're in quake mode or not. + _IsQuakeWindowChanged(nullptr, nullptr); // Tell the window to callback to us when it's about to handle a WM_CREATE auto pfn = std::bind(&AppHost::_HandleCreateWindow, @@ -244,6 +245,7 @@ void AppHost::Initialize() _logic.FullscreenChanged({ this, &AppHost::_FullscreenChanged }); _logic.FocusModeChanged({ this, &AppHost::_FocusModeChanged }); _logic.AlwaysOnTopChanged({ this, &AppHost::_AlwaysOnTopChanged }); + _logic.RaiseVisualBell({ this, &AppHost::_RaiseVisualBell }); _logic.Create(); @@ -399,14 +401,6 @@ void AppHost::_HandleCreateWindow(const HWND hwnd, RECT proposedRect, LaunchMode til::point origin{ ::base::saturated_cast(proposedRect.left), ::base::saturated_cast(proposedRect.top) }; - if (centerOnLaunch) - { - // Move our proposed location into the center of that specific monitor. - origin = til::point{ - nearestMonitorInfo.rcWork.left + ((desktopDimensions.width() / 2) - (dimensions.width() / 2)), - nearestMonitorInfo.rcWork.top + ((desktopDimensions.height() / 2) - (dimensions.height() / 2)) - }; - } if (_logic.IsQuakeWindow()) { @@ -416,8 +410,8 @@ void AppHost::_HandleCreateWindow(const HWND hwnd, RECT proposedRect, LaunchMode const til::size availableSpace = desktopDimensions + nonClientSize; origin = til::point{ - nearestMonitorInfo.rcWork.left - (nonClientSize.width() / 2), - nearestMonitorInfo.rcWork.top + ::base::saturated_cast(nearestMonitorInfo.rcWork.left - (nonClientSize.width() / 2)), + ::base::saturated_cast(nearestMonitorInfo.rcWork.top) }; dimensions = til::size{ availableSpace.width(), @@ -425,9 +419,16 @@ void AppHost::_HandleCreateWindow(const HWND hwnd, RECT proposedRect, LaunchMode }; launchMode = LaunchMode::FocusMode; } + else if (centerOnLaunch) + { + // Move our proposed location into the center of that specific monitor. + origin = til::point{ + ::base::saturated_cast(nearestMonitorInfo.rcWork.left + ((desktopDimensions.width() / 2) - (dimensions.width() / 2))), + ::base::saturated_cast(nearestMonitorInfo.rcWork.top + ((desktopDimensions.height() / 2) - (dimensions.height() / 2))) + }; + } const til::rectangle newRect{ origin, dimensions }; - // const auto newPos = Viewport::FromDimensions(origin, dimensions); bool succeeded = SetWindowPos(hwnd, nullptr, newRect.left(), diff --git a/src/cascadia/WindowsTerminal/IslandWindow.cpp b/src/cascadia/WindowsTerminal/IslandWindow.cpp index 86ab385ed95..b6fe08ffae8 100644 --- a/src/cascadia/WindowsTerminal/IslandWindow.cpp +++ b/src/cascadia/WindowsTerminal/IslandWindow.cpp @@ -170,7 +170,7 @@ LRESULT IslandWindow::_OnSizing(const WPARAM wParam, const LPARAM lParam) { // If we haven't been given the callback that would adjust the dimension, // then we can't do anything, so just bail out. - return FALSE; + return false; } LPRECT winRect = reinterpret_cast(lParam); @@ -182,8 +182,9 @@ LRESULT IslandWindow::_OnSizing(const WPARAM wParam, const LPARAM lParam) // optional parameter so give two UINTs. UINT dpix = USER_DEFAULT_SCREEN_DPI; UINT dpiy = USER_DEFAULT_SCREEN_DPI; - // If this fails, we'll use the default of 96. - GetDpiForMonitor(hmon, MDT_EFFECTIVE_DPI, &dpix, &dpiy); + // If this fails, we'll use the default of 96. I think it can only fail for + // bad parameters, which we won't have, so no big deal. + LOG_IF_FAILED(GetDpiForMonitor(hmon, MDT_EFFECTIVE_DPI, &dpix, &dpiy)); const auto widthScale = base::ClampedNumeric(dpix) / USER_DEFAULT_SCREEN_DPI; const long minWidthScaled = minimumWidth * widthScale; @@ -196,7 +197,7 @@ LRESULT IslandWindow::_OnSizing(const WPARAM wParam, const LPARAM lParam) auto clientHeight = winRect->bottom - winRect->top - nonClientSize.cy; // If we're the quake window, prevent resizing on all sides except the - // bottom. This also applies to resising with the Alt+Space menu + // bottom. This also applies to resizing with the Alt+Space menu if (IsQuakeWindow() && wParam != WMSZ_BOTTOM) { // Stuff our current window size into the lParam, and return true. This @@ -254,7 +255,7 @@ LRESULT IslandWindow::_OnSizing(const WPARAM wParam, const LPARAM lParam) break; } - return TRUE; + return true; } // Method Description: @@ -929,7 +930,8 @@ void IslandWindow::IsQuakeWindow(bool isQuakeWindow) noexcept if (_isQuakeWindow != isQuakeWindow) { _isQuakeWindow = isQuakeWindow; - if (IsQuakeWindow()) + // Don't enter quake mode if we don't have an HWND yet + if (IsQuakeWindow() && _window) { _enterQuakeMode(); } @@ -938,20 +940,26 @@ void IslandWindow::IsQuakeWindow(bool isQuakeWindow) noexcept void IslandWindow::_enterQuakeMode() { + if (!_window) + { + return; + } + RECT windowRect = GetWindowRect(); HMONITOR hmon = MonitorFromRect(&windowRect, MONITOR_DEFAULTTONEAREST); MONITORINFO nearestMonitorInfo; UINT dpix = USER_DEFAULT_SCREEN_DPI; UINT dpiy = USER_DEFAULT_SCREEN_DPI; - // If this fails, we'll use the default of 96. - GetDpiForMonitor(hmon, MDT_EFFECTIVE_DPI, &dpix, &dpiy); + // If this fails, we'll use the default of 96. I think it can only fail for + // bad parameters, which we won't have, so no big deal. + LOG_IF_FAILED(GetDpiForMonitor(hmon, MDT_EFFECTIVE_DPI, &dpix, &dpiy)); nearestMonitorInfo.cbSize = sizeof(MONITORINFO); // Get monitor dimensions: GetMonitorInfo(hmon, &nearestMonitorInfo); - const til::size desktopDimensions{ gsl::narrow(nearestMonitorInfo.rcWork.right - nearestMonitorInfo.rcWork.left), - gsl::narrow(nearestMonitorInfo.rcWork.bottom - nearestMonitorInfo.rcWork.top) }; + const til::size desktopDimensions{ ::base::saturated_cast(nearestMonitorInfo.rcWork.right - nearestMonitorInfo.rcWork.left), + ::base::saturated_cast(nearestMonitorInfo.rcWork.bottom - nearestMonitorInfo.rcWork.top) }; // If we just use rcWork by itself, we'll fail to account for the invisible // space reserved for the resize handles. So retrieve that size here. @@ -959,8 +967,8 @@ void IslandWindow::_enterQuakeMode() const til::size availableSpace = desktopDimensions + ncSize; const til::point origin{ - ::base::saturated_cast(nearestMonitorInfo.rcWork.left - (ncSize.width() / 2)), - ::base::saturated_cast(nearestMonitorInfo.rcWork.top) + ::base::saturated_cast(nearestMonitorInfo.rcWork.left - (ncSize.width() / 2)), + ::base::saturated_cast(nearestMonitorInfo.rcWork.top) }; const til::size dimensions{ availableSpace.width(), diff --git a/src/cascadia/WindowsTerminal/NonClientIslandWindow.cpp b/src/cascadia/WindowsTerminal/NonClientIslandWindow.cpp index b45595ba245..eb4e6400ed4 100644 --- a/src/cascadia/WindowsTerminal/NonClientIslandWindow.cpp +++ b/src/cascadia/WindowsTerminal/NonClientIslandWindow.cpp @@ -532,7 +532,7 @@ int NonClientIslandWindow::_GetResizeHandleHeight() const noexcept const auto originalRet = DefWindowProc(_window.get(), WM_NCHITTEST, 0, lParam); if (originalRet != HTCLIENT) { - // If we're the quake window, supress resizing on any side except the + // If we're the quake window, suppress resizing on any side except the // bottom. I don't believe that this actually works on the top. That's // handled below. if (IsQuakeWindow()) From 1e43eefad9c5fcc27066601dc0e7bab8bce85675 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Thu, 15 Apr 2021 09:30:32 -0500 Subject: [PATCH 8/9] some of this logic was weird --- src/cascadia/TerminalApp/AppLogic.cpp | 4 ++++ src/cascadia/TerminalApp/TerminalPage.cpp | 11 +++++++---- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/cascadia/TerminalApp/AppLogic.cpp b/src/cascadia/TerminalApp/AppLogic.cpp index ee1706f8364..487b2bd6c8d 100644 --- a/src/cascadia/TerminalApp/AppLogic.cpp +++ b/src/cascadia/TerminalApp/AppLogic.cpp @@ -285,6 +285,10 @@ namespace winrt::TerminalApp::implementation // launched _fullscreen_, toggle fullscreen mode. This will make sure // that the window size is _first_ set up as something sensible, so // leaving fullscreen returns to a reasonable size. + // + // We know at the start, that the root TerminalPage definitely isn't + // in focus nor fullscreen mode. So "Toggle" here will always work + // to "enable". const auto launchMode = this->GetLaunchMode(); if (IsQuakeWindow()) { diff --git a/src/cascadia/TerminalApp/TerminalPage.cpp b/src/cascadia/TerminalApp/TerminalPage.cpp index 9b5cc911657..38e51a05899 100644 --- a/src/cascadia/TerminalApp/TerminalPage.cpp +++ b/src/cascadia/TerminalApp/TerminalPage.cpp @@ -2056,9 +2056,12 @@ namespace winrt::TerminalApp::implementation void TerminalPage::_SetFocusMode(const bool inFocusMode) { - if (inFocusMode != FocusMode()) + // If we're the quake window, we must always be in focus mode. + // Prevent leaving focus mode here. + const bool newInFocusMode = inFocusMode || IsQuakeWindow(); + if (newInFocusMode != FocusMode()) { - _isInFocusMode = inFocusMode || IsQuakeWindow(); + _isInFocusMode = newInFocusMode; _UpdateTabView(); _FocusModeChangedHandlers(*this, nullptr); } @@ -2270,7 +2273,7 @@ namespace winrt::TerminalApp::implementation bool TerminalPage::FocusMode() const { - return _isInFocusMode || IsQuakeWindow(); + return _isInFocusMode; } bool TerminalPage::Fullscreen() const @@ -2618,7 +2621,7 @@ namespace winrt::TerminalApp::implementation // If we're entering Quake Mode from ~Focus Mode, then this will enter Focus Mode // If we're entering Quake Mode from Focus Mode, then this will do nothing // If we're leaving Quake Mode (we're already in Focus Mode), then this will do nothing - _SetFocusMode(_isInFocusMode); + _SetFocusMode(true); _IsQuakeWindowChangedHandlers(*this, nullptr); } } From beb96e3a359613b221b8f8a3fc2b5ffb220ee370 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Fri, 16 Apr 2021 10:30:22 -0500 Subject: [PATCH 9/9] give til the `long` superpower --- src/cascadia/WindowsTerminal/AppHost.cpp | 12 ++++++------ src/cascadia/WindowsTerminal/IslandWindow.cpp | 8 ++++---- src/inc/til/point.h | 13 +++++++++++++ src/inc/til/size.h | 5 +++++ 4 files changed, 28 insertions(+), 10 deletions(-) diff --git a/src/cascadia/WindowsTerminal/AppHost.cpp b/src/cascadia/WindowsTerminal/AppHost.cpp index 876b50bba82..b25e96ece22 100644 --- a/src/cascadia/WindowsTerminal/AppHost.cpp +++ b/src/cascadia/WindowsTerminal/AppHost.cpp @@ -399,8 +399,8 @@ void AppHost::_HandleCreateWindow(const HWND hwnd, RECT proposedRect, LaunchMode const til::size desktopDimensions{ gsl::narrow(nearestMonitorInfo.rcWork.right - nearestMonitorInfo.rcWork.left), gsl::narrow(nearestMonitorInfo.rcWork.bottom - nearestMonitorInfo.rcWork.top) }; - til::point origin{ ::base::saturated_cast(proposedRect.left), - ::base::saturated_cast(proposedRect.top) }; + til::point origin{ (proposedRect.left), + (proposedRect.top) }; if (_logic.IsQuakeWindow()) { @@ -410,8 +410,8 @@ void AppHost::_HandleCreateWindow(const HWND hwnd, RECT proposedRect, LaunchMode const til::size availableSpace = desktopDimensions + nonClientSize; origin = til::point{ - ::base::saturated_cast(nearestMonitorInfo.rcWork.left - (nonClientSize.width() / 2)), - ::base::saturated_cast(nearestMonitorInfo.rcWork.top) + ::base::ClampSub(nearestMonitorInfo.rcWork.left, (nonClientSize.width() / 2)), + (nearestMonitorInfo.rcWork.top) }; dimensions = til::size{ availableSpace.width(), @@ -423,8 +423,8 @@ void AppHost::_HandleCreateWindow(const HWND hwnd, RECT proposedRect, LaunchMode { // Move our proposed location into the center of that specific monitor. origin = til::point{ - ::base::saturated_cast(nearestMonitorInfo.rcWork.left + ((desktopDimensions.width() / 2) - (dimensions.width() / 2))), - ::base::saturated_cast(nearestMonitorInfo.rcWork.top + ((desktopDimensions.height() / 2) - (dimensions.height() / 2))) + (nearestMonitorInfo.rcWork.left + ((desktopDimensions.width() / 2) - (dimensions.width() / 2))), + (nearestMonitorInfo.rcWork.top + ((desktopDimensions.height() / 2) - (dimensions.height() / 2))) }; } diff --git a/src/cascadia/WindowsTerminal/IslandWindow.cpp b/src/cascadia/WindowsTerminal/IslandWindow.cpp index b6fe08ffae8..adc8fa60f8a 100644 --- a/src/cascadia/WindowsTerminal/IslandWindow.cpp +++ b/src/cascadia/WindowsTerminal/IslandWindow.cpp @@ -958,8 +958,8 @@ void IslandWindow::_enterQuakeMode() nearestMonitorInfo.cbSize = sizeof(MONITORINFO); // Get monitor dimensions: GetMonitorInfo(hmon, &nearestMonitorInfo); - const til::size desktopDimensions{ ::base::saturated_cast(nearestMonitorInfo.rcWork.right - nearestMonitorInfo.rcWork.left), - ::base::saturated_cast(nearestMonitorInfo.rcWork.bottom - nearestMonitorInfo.rcWork.top) }; + const til::size desktopDimensions{ (nearestMonitorInfo.rcWork.right - nearestMonitorInfo.rcWork.left), + (nearestMonitorInfo.rcWork.bottom - nearestMonitorInfo.rcWork.top) }; // If we just use rcWork by itself, we'll fail to account for the invisible // space reserved for the resize handles. So retrieve that size here. @@ -967,8 +967,8 @@ void IslandWindow::_enterQuakeMode() const til::size availableSpace = desktopDimensions + ncSize; const til::point origin{ - ::base::saturated_cast(nearestMonitorInfo.rcWork.left - (ncSize.width() / 2)), - ::base::saturated_cast(nearestMonitorInfo.rcWork.top) + ::base::ClampSub(nearestMonitorInfo.rcWork.left, (ncSize.width() / 2)), + (nearestMonitorInfo.rcWork.top) }; const til::size dimensions{ availableSpace.width(), diff --git a/src/inc/til/point.h b/src/inc/til/point.h index 87c802ebb27..366ba18077b 100644 --- a/src/inc/til/point.h +++ b/src/inc/til/point.h @@ -25,6 +25,14 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned" point(static_cast(x), static_cast(y)) { } + constexpr point(ptrdiff_t width, int height) noexcept : + point(width, static_cast(height)) + { + } + constexpr point(int width, ptrdiff_t height) noexcept : + point(static_cast(width), height) + { + } #endif point(size_t x, size_t y) @@ -32,6 +40,11 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned" THROW_HR_IF(E_ABORT, !base::MakeCheckedNum(x).AssignIfValid(&_x)); THROW_HR_IF(E_ABORT, !base::MakeCheckedNum(y).AssignIfValid(&_y)); } + point(long x, long y) + { + THROW_HR_IF(E_ABORT, !base::MakeCheckedNum(x).AssignIfValid(&_x)); + THROW_HR_IF(E_ABORT, !base::MakeCheckedNum(y).AssignIfValid(&_y)); + } constexpr point(ptrdiff_t x, ptrdiff_t y) noexcept : _x(x), diff --git a/src/inc/til/size.h b/src/inc/til/size.h index 383cb13d92e..907089ef690 100644 --- a/src/inc/til/size.h +++ b/src/inc/til/size.h @@ -40,6 +40,11 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned" THROW_HR_IF(E_ABORT, !base::MakeCheckedNum(width).AssignIfValid(&_width)); THROW_HR_IF(E_ABORT, !base::MakeCheckedNum(height).AssignIfValid(&_height)); } + size(long width, long height) + { + THROW_HR_IF(E_ABORT, !base::MakeCheckedNum(width).AssignIfValid(&_width)); + THROW_HR_IF(E_ABORT, !base::MakeCheckedNum(height).AssignIfValid(&_height)); + } constexpr size(ptrdiff_t width, ptrdiff_t height) noexcept : _width(width),