Repository: microsoft/terminal
File: src/cascadia/WindowsTerminal/AppHost.cpp (C++)

Code before:

// Method Description:
// - Called when no tab is remaining to close the window.
// Arguments:
// - sender: unused
// - LastTabClosedEventArgs: unused
// Return Value:
// - <none>
void AppHost::LastTabClosed(const winrt::Windows::Foundation::IInspectable& /*sender*/, const winrt::TerminalApp::LastTabClosedEventArgs& /*args*/)
{
    if (_windowManager.IsMonarch() && _notificationIcon)
    {
        _DestroyNotificationIcon();
    }
    else if (_window->IsQuakeWindow())
    {
        _HideNotificationIconRequested();
    }

    _window->Close();
}

LaunchPosition AppHost::_GetWindowLaunchPosition()
{
    // Get the position of the current window. This includes the
    // non-client already.
    const auto window = _window->GetWindowRect();

    const auto dpi = _window->GetCurrentDpi();
    const auto nonClientArea = _window->GetNonClientFrame(dpi);

    // The nonClientArea adjustment is negative, so subtract that out.
    // This way we save the user-visible location of the terminal.
    LaunchPosition pos{};
    pos.X = window.left - nonClientArea.left;
    pos.Y = window.top;

    return pos;
}

// Method Description:
// - Resize the window we're about to create to the appropriate dimensions, as
//   specified in the settings. This will be called during the handling of
//   WM_CREATE. We'll load the settings for the app, then get the proposed size
//   of the terminal from the app. Using that proposed size, we'll resize the
//   window we're creating, so that it'll match the values in the settings.
// Arguments:
// - hwnd: The HWND of the window we're about to create.
// - proposedRect: The location and size of the window that we're about to
//   create. We'll use this rect to determine which monitor the window is about
//   to appear on.

Review comment (bug):
I added this which makes many of the other changes potentially redundant (but it doesn't hurt to have more checks). Assuming this call doesn't fail somehow, we will try to acquire the lock in the monarch which means we block until any outstanding event handlers finish, and then afterwards we are removed from the list of peasants so we shouldn't be called again.

Edit: I remembered that I made this function do nothing if we are in the middle of a `quit` operation, so it isn't quite as thorough. But also before a quit happens we stop the automatic saving so it is probably fine anyways. :shrug: Enforcing all of the invariants I want is a pain.

Code after:

// Method Description:
// - Called when no tab is remaining to close the window.
// Arguments:
// - sender: unused
// - LastTabClosedEventArgs: unused
// Return Value:
// - <none>
void AppHost::LastTabClosed(const winrt::Windows::Foundation::IInspectable& /*sender*/, const winrt::TerminalApp::LastTabClosedEventArgs& /*args*/)
{
    if (_windowManager.IsMonarch() && _notificationIcon)
    {
        _DestroyNotificationIcon();
    }
    else if (_window->IsQuakeWindow())
    {
        _HideNotificationIconRequested();
    }

    // We don't want to try to save layouts if we are about to close
    _getWindowLayoutThrottler.reset();
    _windowManager.GetWindowLayoutRequested(_GetWindowLayoutRequestedToken);
    // Remove ourself from the list of peasants so that we aren't included in
    // any future requests. This will also mean we block until any existing
    // event handler finishes.
    _windowManager.SignalClose();

    _window->Close();
}

LaunchPosition AppHost::_GetWindowLaunchPosition()
{
    LaunchPosition pos{};
    // If we started saving before closing, but didn't resume the event handler
    // until after _window might be a nullptr.
    if (!_window)
    {
        return pos;
    }

    try
    {
        // Get the position of the current window. This includes the
        // non-client already.
        const auto window = _window->GetWindowRect();

        const auto dpi = _window->GetCurrentDpi();
        const auto nonClientArea = _window->GetNonClientFrame(dpi);

        // The nonClientArea adjustment is negative, so subtract that out.
        // This way we save the user-visible location of the terminal.