Skip to content

Commit

Permalink
Account for the window frame when calculating initial position (#10902)
Browse files Browse the repository at this point in the history
## Summary of the Pull Request

Turns out, we'd only ever use the non-client size to calculate the size of the window, but not the actual position. As we learned in #10676, the nonclient area extends a few pixels past the visible borders of the window. 

## PR Checklist
* [x] Closes #10583
* [x] I work here
* [ ] Tests added/passed
* [n/a] Requires documentation to be updated

## Validation Steps Performed
* [x] Works with the `IslandWindow`
* [x] Works with the `NonClientIslandWindow`
  • Loading branch information
zadjii-msft authored Aug 9, 2021
1 parent cd4aabd commit 7acec30
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 13 deletions.
9 changes: 7 additions & 2 deletions src/cascadia/WindowsTerminal/AppHost.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<long>();
adjustedHeight = islandHeight + nonClientSize.height<long>();

Expand All @@ -425,14 +426,18 @@ void AppHost::_HandleCreateWindow(const HWND hwnd, RECT proposedRect, LaunchMode
const til::size desktopDimensions{ gsl::narrow<short>(nearestMonitorInfo.rcWork.right - nearestMonitorInfo.rcWork.left),
gsl::narrow<short>(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<LONG>()),
(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{
Expand Down
29 changes: 24 additions & 5 deletions src/cascadia/WindowsTerminal/IslandWindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<DWORD>(GetWindowLong(_window.get(), GWL_STYLE));
RECT islandFrame{};
Expand All @@ -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
Expand Down
1 change: 1 addition & 0 deletions src/cascadia/WindowsTerminal/IslandWindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ class IslandWindow :
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();
Expand Down
31 changes: 25 additions & 6 deletions src/cascadia/WindowsTerminal/NonClientIslandWindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<DWORD>(GetWindowLong(_window.get(), GWL_STYLE));
RECT islandFrame{};
Expand All @@ -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.
Expand Down
1 change: 1 addition & 0 deletions src/cascadia/WindowsTerminal/NonClientIslandWindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ class NonClientIslandWindow : public IslandWindow

[[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;
Expand Down

0 comments on commit 7acec30

Please sign in to comment.