diff --git a/src/cascadia/WindowsTerminal/AppHost.cpp b/src/cascadia/WindowsTerminal/AppHost.cpp index 092fe8eae..bb1b0889e 100644 --- a/src/cascadia/WindowsTerminal/AppHost.cpp +++ b/src/cascadia/WindowsTerminal/AppHost.cpp @@ -410,6 +410,7 @@ 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 til::size nonClientSize = _window->GetTotalNonClientExclusiveSize(dpix); + const til::rectangle nonClientFrame = _window->GetNonClientFrame(dpix); adjustedWidth = islandWidth + nonClientSize.width(); adjustedHeight = islandHeight + nonClientSize.height(); @@ -425,14 +426,18 @@ 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{ (proposedRect.left), + // GH#10583 - Adjust the position of the rectangle to account for the size + // of the invisible borders on the left/right. We DON'T want to adjust this + // for the top here - the IslandWindow includes the titlebar in + // nonClientFrame.top, so adjusting for that would actually place the + // titlebar _off_ the monitor. + til::point origin{ (proposedRect.left + nonClientFrame.left()), (proposedRect.top) }; if (_logic.IsQuakeWindow()) { // 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{ diff --git a/src/cascadia/WindowsTerminal/IslandWindow.cpp b/src/cascadia/WindowsTerminal/IslandWindow.cpp index 50fd2d156..5d8f823de 100644 --- a/src/cascadia/WindowsTerminal/IslandWindow.cpp +++ b/src/cascadia/WindowsTerminal/IslandWindow.cpp @@ -616,12 +616,20 @@ void IslandWindow::SetContent(winrt::Windows::UI::Xaml::UIElement content) } // Method Description: -// - Gets the difference between window and client area size. +// - Get the dimensions of our non-client area, as a rect where each component +// represents that side. +// - The .left will be a negative number, to represent that the actual side of +// the non-client area is outside the border of our window. It's roughly 8px ( +// * DPI scaling) to the left of the visible border. +// - The .right component will be positive, indicating that the nonclient border +// is in the positive-x direction from the edge of our client area. +// - This will also include our titlebar! It's in the nonclient area for us. // Arguments: -// - dpi: dpi of a monitor on which the window is placed -// Return Value -// - The size difference -SIZE IslandWindow::GetTotalNonClientExclusiveSize(const UINT dpi) const noexcept +// - dpi: the scaling that we should use to calculate the border sizes. +// Return Value: +// - a RECT whose components represent the margins of the nonclient area, +// relative to the client area. +RECT IslandWindow::GetNonClientFrame(const UINT dpi) const noexcept { const auto windowStyle = static_cast(GetWindowLong(_window.get(), GWL_STYLE)); RECT islandFrame{}; @@ -630,7 +638,18 @@ SIZE IslandWindow::GetTotalNonClientExclusiveSize(const UINT dpi) const noexcept // the error and go on. We'll use whatever the control proposed as the // size of our window, which will be at least close. LOG_IF_WIN32_BOOL_FALSE(AdjustWindowRectExForDpi(&islandFrame, windowStyle, false, 0, dpi)); + return islandFrame; +} +// Method Description: +// - Gets the difference between window and client area size. +// Arguments: +// - dpi: dpi of a monitor on which the window is placed +// Return Value +// - The size difference +SIZE IslandWindow::GetTotalNonClientExclusiveSize(const UINT dpi) const noexcept +{ + const auto islandFrame{ GetNonClientFrame(dpi) }; return { islandFrame.right - islandFrame.left, islandFrame.bottom - islandFrame.top diff --git a/src/cascadia/WindowsTerminal/IslandWindow.h b/src/cascadia/WindowsTerminal/IslandWindow.h index 8e4a0ec4d..b0699864d 100644 --- a/src/cascadia/WindowsTerminal/IslandWindow.h +++ b/src/cascadia/WindowsTerminal/IslandWindow.h @@ -24,6 +24,7 @@ public: virtual void OnAppInitialized(); virtual void SetContent(winrt::Windows::UI::Xaml::UIElement content); virtual void OnApplicationThemeChanged(const winrt::Windows::UI::Xaml::ElementTheme& requestedTheme); + virtual RECT GetNonClientFrame(const UINT dpi) const noexcept; virtual SIZE GetTotalNonClientExclusiveSize(const UINT dpi) const noexcept; virtual void Initialize(); diff --git a/src/cascadia/WindowsTerminal/NonClientIslandWindow.cpp b/src/cascadia/WindowsTerminal/NonClientIslandWindow.cpp index a1f5e6801..9dc8307ed 100644 --- a/src/cascadia/WindowsTerminal/NonClientIslandWindow.cpp +++ b/src/cascadia/WindowsTerminal/NonClientIslandWindow.cpp @@ -629,14 +629,21 @@ int NonClientIslandWindow::_GetResizeHandleHeight() const noexcept return DefWindowProc(GetHandle(), WM_SETCURSOR, wParam, lParam); } - // Method Description: -// - Gets the difference between window and client area size. +// - Get the dimensions of our non-client area, as a rect where each component +// represents that side. +// - The .left will be a negative number, to represent that the actual side of +// the non-client area is outside the border of our window. It's roughly 8px ( +// * DPI scaling) to the left of the visible border. +// - The .right component will be positive, indicating that the nonclient border +// is in the positive-x direction from the edge of our client area. +// - This DOES NOT include our titlebar! It's in the client area for us. // Arguments: -// - dpi: dpi of a monitor on which the window is placed -// Return Value -// - The size difference -SIZE NonClientIslandWindow::GetTotalNonClientExclusiveSize(UINT dpi) const noexcept +// - dpi: the scaling that we should use to calculate the border sizes. +// Return Value: +// - a RECT whose components represent the margins of the nonclient area, +// relative to the client area. +RECT NonClientIslandWindow::GetNonClientFrame(UINT dpi) const noexcept { const auto windowStyle = static_cast(GetWindowLong(_window.get(), GWL_STYLE)); RECT islandFrame{}; @@ -647,6 +654,18 @@ SIZE NonClientIslandWindow::GetTotalNonClientExclusiveSize(UINT dpi) const noexc LOG_IF_WIN32_BOOL_FALSE(AdjustWindowRectExForDpi(&islandFrame, windowStyle, false, 0, dpi)); islandFrame.top = -topBorderVisibleHeight; + return islandFrame; +} + +// Method Description: +// - Gets the difference between window and client area size. +// Arguments: +// - dpi: dpi of a monitor on which the window is placed +// Return Value +// - The size difference +SIZE NonClientIslandWindow::GetTotalNonClientExclusiveSize(UINT dpi) const noexcept +{ + const auto islandFrame{ GetNonClientFrame(dpi) }; // If we have a titlebar, this is being called after we've initialized, and // we can just ask that titlebar how big it wants to be. diff --git a/src/cascadia/WindowsTerminal/NonClientIslandWindow.h b/src/cascadia/WindowsTerminal/NonClientIslandWindow.h index 10a39b4fc..02e59cc7a 100644 --- a/src/cascadia/WindowsTerminal/NonClientIslandWindow.h +++ b/src/cascadia/WindowsTerminal/NonClientIslandWindow.h @@ -37,6 +37,7 @@ public: [[nodiscard]] virtual LRESULT MessageHandler(UINT const message, WPARAM const wparam, LPARAM const lparam) noexcept override; + virtual RECT GetNonClientFrame(UINT dpi) const noexcept override; virtual SIZE GetTotalNonClientExclusiveSize(UINT dpi) const noexcept override; void Initialize() override;