Handle window resize event (CSI t, resize) (#17721)

`ResizeWindow` event in `TerminalApi` is handled and bubbled to
`TerminalApi->ControlCore->TermControl->TerminalPage->AppHost`. Resizing
is accepted only if the window is not in fullscreen or quake mode, and
has 1 tab and pane.

Relevant issues: #5094
This commit is contained in:
Nihat Uygar Köseer 2024-08-29 21:43:50 +03:00 committed by GitHub
parent 93d592bb41
commit 837215b206
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
24 changed files with 248 additions and 4 deletions

View File

@ -1743,6 +1743,8 @@ namespace winrt::TerminalApp::implementation
term.SearchMissingCommand({ get_weak(), &TerminalPage::_SearchMissingCommandHandler });
term.WindowSizeChanged({ get_weak(), &TerminalPage::_WindowSizeChanged });
// Don't even register for the event if the feature is compiled off.
if constexpr (Feature_ShellCompletions::IsEnabled())
{
@ -3090,6 +3092,31 @@ namespace winrt::TerminalApp::implementation
term.RefreshQuickFixMenu();
}
void TerminalPage::_WindowSizeChanged(const IInspectable sender, const Microsoft::Terminal::Control::WindowSizeChangedEventArgs args)
{
// Raise if:
// - Not in quake mode
// - Not in fullscreen
// - Only one tab exists
// - Only one pane exists
// else:
// - Reset conpty to its original size back
if (!WindowProperties().IsQuakeWindow() && !Fullscreen() &&
NumberOfTabs() == 1 && _GetFocusedTabImpl()->GetLeafPaneCount() == 1)
{
WindowSizeChanged.raise(*this, args);
}
else if (const auto& control{ sender.try_as<TermControl>() })
{
const auto& connection = control.Connection();
if (const auto& conpty{ connection.try_as<TerminalConnection::ConptyConnection>() })
{
conpty.ResetSize();
}
}
}
// Method Description:
// - Paste text from the Windows Clipboard to the focused terminal
void TerminalPage::_PasteText()

View File

@ -195,6 +195,7 @@ namespace winrt::TerminalApp::implementation
til::typed_event<IInspectable, IInspectable> IdentifyWindowsRequested;
til::typed_event<IInspectable, winrt::TerminalApp::RenameWindowRequestedArgs> RenameWindowRequested;
til::typed_event<IInspectable, IInspectable> SummonWindowRequested;
til::typed_event<IInspectable, winrt::Microsoft::Terminal::Control::WindowSizeChangedEventArgs> WindowSizeChanged;
til::typed_event<IInspectable, IInspectable> CloseRequested;
til::typed_event<IInspectable, IInspectable> OpenSystemMenu;
@ -541,6 +542,7 @@ namespace winrt::TerminalApp::implementation
Windows::Foundation::IAsyncAction _SearchMissingCommandHandler(const IInspectable sender, const winrt::Microsoft::Terminal::Control::SearchMissingCommandEventArgs args);
Windows::Foundation::IAsyncOperation<Windows::Foundation::Collections::IVectorView<winrt::Microsoft::Management::Deployment::MatchResult>> _FindPackageAsync(hstring query);
void _WindowSizeChanged(const IInspectable sender, const winrt::Microsoft::Terminal::Control::WindowSizeChangedEventArgs args);
safe_void_coroutine _windowPropertyChanged(const IInspectable& sender, const winrt::Windows::UI::Xaml::Data::PropertyChangedEventArgs& args);
void _onTabDragStarting(const winrt::Microsoft::UI::Xaml::Controls::TabView& sender, const winrt::Microsoft::UI::Xaml::Controls::TabViewTabDragStartingEventArgs& e);

View File

@ -100,6 +100,7 @@ namespace TerminalApp
event Windows.Foundation.TypedEventHandler<Object, Object> IdentifyWindowsRequested;
event Windows.Foundation.TypedEventHandler<Object, RenameWindowRequestedArgs> RenameWindowRequested;
event Windows.Foundation.TypedEventHandler<Object, Object> SummonWindowRequested;
event Windows.Foundation.TypedEventHandler<Object, Microsoft.Terminal.Control.WindowSizeChangedEventArgs> WindowSizeChanged;
event Windows.Foundation.TypedEventHandler<Object, Object> CloseRequested;
event Windows.Foundation.TypedEventHandler<Object, Object> OpenSystemMenu;

View File

@ -15,6 +15,7 @@
using namespace winrt::Windows::ApplicationModel;
using namespace winrt::Windows::ApplicationModel::DataTransfer;
using namespace winrt::Windows::Graphics::Display;
using namespace winrt::Windows::UI::Xaml;
using namespace winrt::Windows::UI::Xaml::Controls;
using namespace winrt::Windows::UI::Core;
@ -217,6 +218,7 @@ namespace winrt::TerminalApp::implementation
_root->SetSettings(_settings, false); // We're on our UI thread right now, so this is safe
_root->Loaded({ get_weak(), &TerminalWindow::_OnLoaded });
_root->Initialized({ get_weak(), &TerminalWindow::_pageInitialized });
_root->WindowSizeChanged({ get_weak(), &TerminalWindow::_WindowSizeChanged });
_root->Create();
AppLogic::Current()->SettingsChanged({ get_weak(), &TerminalWindow::UpdateSettingsHandler });
@ -1331,6 +1333,41 @@ namespace winrt::TerminalApp::implementation
}
}
void TerminalWindow::_WindowSizeChanged(const IInspectable&, winrt::Microsoft::Terminal::Control::WindowSizeChangedEventArgs args)
{
winrt::Windows::Foundation::Size pixelSize = { static_cast<float>(args.Width()), static_cast<float>(args.Height()) };
const auto scale = static_cast<float>(DisplayInformation::GetForCurrentView().RawPixelsPerViewPixel());
if (!FocusMode())
{
if (!_settings.GlobalSettings().AlwaysShowTabs())
{
// Hide the title bar = off, Always show tabs = off.
static constexpr auto titlebarHeight = 10;
pixelSize.Height += (titlebarHeight)*scale;
}
else if (!_settings.GlobalSettings().ShowTabsInTitlebar())
{
// Hide the title bar = off, Always show tabs = on.
static constexpr auto titlebarAndTabBarHeight = 40;
pixelSize.Height += (titlebarAndTabBarHeight)*scale;
}
// Hide the title bar = on, Always show tabs = on.
// In this case, we don't add any height because
// NonClientIslandWindow::GetTotalNonClientExclusiveSize() gets
// called in AppHost::_resizeWindow and it already takes title bar
// height into account. In other cases above
// IslandWindow::GetTotalNonClientExclusiveSize() is called, and it
// doesn't take the title bar height into account, so we have to do
// the calculation manually.
}
args.Width(static_cast<int32_t>(pixelSize.Width));
args.Height(static_cast<int32_t>(pixelSize.Height));
WindowSizeChanged.raise(*this, args);
}
winrt::hstring WindowProperties::WindowName() const noexcept
{
return _WindowName;

View File

@ -162,6 +162,7 @@ namespace winrt::TerminalApp::implementation
til::typed_event<Windows::Foundation::IInspectable, Windows::Foundation::IInspectable> IsQuakeWindowChanged;
til::typed_event<winrt::Windows::Foundation::IInspectable, winrt::TerminalApp::SystemMenuChangeArgs> SystemMenuChangeRequested;
til::typed_event<winrt::Windows::Foundation::IInspectable, winrt::TerminalApp::SettingsLoadEventArgs> SettingsChanged;
til::typed_event<winrt::Windows::Foundation::IInspectable, winrt::Microsoft::Terminal::Control::WindowSizeChangedEventArgs> WindowSizeChanged;
private:
// If you add controls here, but forget to null them either here or in
@ -202,6 +203,7 @@ namespace winrt::TerminalApp::implementation
void _OnLoaded(const IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& eventArgs);
void _pageInitialized(const IInspectable& sender, const IInspectable& eventArgs);
void _OpenSettingsUI();
void _WindowSizeChanged(const IInspectable& sender, winrt::Microsoft::Terminal::Control::WindowSizeChangedEventArgs args);
winrt::Windows::Foundation::Collections::IVector<Microsoft::Terminal::Settings::Model::ActionAndArgs> _contentStringToActions(const winrt::hstring& content,
const bool replaceFirstWithNewTab);

View File

@ -132,6 +132,7 @@ namespace TerminalApp
event Windows.Foundation.TypedEventHandler<Object, Object> QuitRequested;
event Windows.Foundation.TypedEventHandler<Object, TerminalApp.SystemMenuChangeArgs> SystemMenuChangeRequested;
event Windows.Foundation.TypedEventHandler<Object, Microsoft.Terminal.Control.ShowWindowArgs> ShowWindowChanged;
event Windows.Foundation.TypedEventHandler<Object, Microsoft.Terminal.Control.WindowSizeChangedEventArgs> WindowSizeChanged;
event Windows.Foundation.TypedEventHandler<Object, SettingsLoadEventArgs> SettingsChanged;

View File

@ -534,6 +534,14 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
}
}
void ConptyConnection::ResetSize()
{
if (_isConnected())
{
THROW_IF_FAILED(ConptyResizePseudoConsole(_hPC.get(), { Utils::ClampToShortMax(_cols, 1), Utils::ClampToShortMax(_rows, 1) }));
}
}
void ConptyConnection::ClearBuffer()
{
// If we haven't connected yet, then we really don't need to do

View File

@ -23,6 +23,7 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
void Start();
void WriteInput(const winrt::array_view<const char16_t> buffer);
void Resize(uint32_t rows, uint32_t columns);
void ResetSize();
void Close() noexcept;
void ClearBuffer();

View File

@ -14,6 +14,7 @@ namespace Microsoft.Terminal.TerminalConnection
String StartingTitle { get; };
UInt16 ShowWindow { get; };
void ResetSize();
void ClearBuffer();
void ShowHide(Boolean show);

View File

@ -134,6 +134,9 @@ namespace winrt::Microsoft::Terminal::Control::implementation
auto pfnClearQuickFix = [this] { ClearQuickFix(); };
_terminal->SetClearQuickFixCallback(pfnClearQuickFix);
auto pfnWindowSizeChanged = [this](auto&& PH1, auto&& PH2) { _terminalWindowSizeChanged(std::forward<decltype(PH1)>(PH1), std::forward<decltype(PH2)>(PH2)); };
_terminal->SetWindowSizeChangedCallback(pfnWindowSizeChanged);
// MSFT 33353327: Initialize the renderer in the ctor instead of Initialize().
// We need the renderer to be ready to accept new engines before the SwapChainPanel is ready to go.
// If we wait, a screen reader may try to get the AutomationPeer (aka the UIA Engine), and we won't be able to attach
@ -1629,6 +1632,12 @@ namespace winrt::Microsoft::Terminal::Control::implementation
_midiAudio.PlayNote(reinterpret_cast<HWND>(_owningHwnd), noteNumber, velocity, std::chrono::duration_cast<std::chrono::milliseconds>(duration));
}
void ControlCore::_terminalWindowSizeChanged(int32_t width, int32_t height)
{
auto size = winrt::make<implementation::WindowSizeChangedEventArgs>(width, height);
WindowSizeChanged.raise(*this, size);
}
void ControlCore::_terminalSearchMissingCommand(std::wstring_view missingCommand, const til::CoordType& bufferRow)
{
SearchMissingCommand.raise(*this, make<implementation::SearchMissingCommandEventArgs>(hstring{ missingCommand }, bufferRow));

View File

@ -295,6 +295,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
til::typed_event<IInspectable, Control::CompletionsChangedEventArgs> CompletionsChanged;
til::typed_event<IInspectable, Control::SearchMissingCommandEventArgs> SearchMissingCommand;
til::typed_event<> RefreshQuickFixUI;
til::typed_event<IInspectable, Control::WindowSizeChangedEventArgs> WindowSizeChanged;
til::typed_event<> CloseTerminalRequested;
til::typed_event<> RestartTerminalRequested;
@ -391,6 +392,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
const int velocity,
const std::chrono::microseconds duration);
void _terminalSearchMissingCommand(std::wstring_view missingCommand, const til::CoordType& bufferRow);
void _terminalWindowSizeChanged(int32_t width, int32_t height);
safe_void_coroutine _terminalCompletionsChanged(std::wstring_view menuJson, unsigned int replaceLength);

View File

@ -190,6 +190,7 @@ namespace Microsoft.Terminal.Control
event Windows.Foundation.TypedEventHandler<Object, ShowWindowArgs> ShowWindowChanged;
event Windows.Foundation.TypedEventHandler<Object, SearchMissingCommandEventArgs> SearchMissingCommand;
event Windows.Foundation.TypedEventHandler<Object, Object> RefreshQuickFixUI;
event Windows.Foundation.TypedEventHandler<Object, WindowSizeChangedEventArgs> WindowSizeChanged;
// These events are always called from the UI thread (bugs aside)
event Windows.Foundation.TypedEventHandler<Object, FontSizeChangedArgs> FontSizeChanged;

View File

@ -19,3 +19,4 @@
#include "CharSentEventArgs.g.cpp"
#include "StringSentEventArgs.g.cpp"
#include "SearchMissingCommandEventArgs.g.cpp"
#include "WindowSizeChangedEventArgs.g.cpp"

View File

@ -19,6 +19,7 @@
#include "CharSentEventArgs.g.h"
#include "StringSentEventArgs.g.h"
#include "SearchMissingCommandEventArgs.g.h"
#include "WindowSizeChangedEventArgs.g.h"
namespace winrt::Microsoft::Terminal::Control::implementation
{
@ -223,6 +224,20 @@ namespace winrt::Microsoft::Terminal::Control::implementation
til::property<winrt::hstring> MissingCommand;
til::property<til::CoordType> BufferRow;
};
struct WindowSizeChangedEventArgs : public WindowSizeChangedEventArgsT<WindowSizeChangedEventArgs>
{
public:
WindowSizeChangedEventArgs(int32_t width,
int32_t height) :
_Width(width),
_Height(height)
{
}
WINRT_PROPERTY(int32_t, Width);
WINRT_PROPERTY(int32_t, Height);
};
}
namespace winrt::Microsoft::Terminal::Control::factory_implementation

View File

@ -132,4 +132,10 @@ namespace Microsoft.Terminal.Control
String MissingCommand { get; };
Int32 BufferRow { get; };
}
runtimeclass WindowSizeChangedEventArgs
{
Int32 Width;
Int32 Height;
}
}

View File

@ -224,6 +224,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
_revokers.CompletionsChanged = _core.CompletionsChanged(winrt::auto_revoke, { get_weak(), &TermControl::_bubbleCompletionsChanged });
_revokers.RestartTerminalRequested = _core.RestartTerminalRequested(winrt::auto_revoke, { get_weak(), &TermControl::_bubbleRestartTerminalRequested });
_revokers.SearchMissingCommand = _core.SearchMissingCommand(winrt::auto_revoke, { get_weak(), &TermControl::_bubbleSearchMissingCommand });
_revokers.WindowSizeChanged = _core.WindowSizeChanged(winrt::auto_revoke, { get_weak(), &TermControl::_bubbleWindowSizeChanged });
_revokers.PasteFromClipboard = _interactivity.PasteFromClipboard(winrt::auto_revoke, { get_weak(), &TermControl::_bubblePasteFromClipboard });
@ -2779,6 +2780,42 @@ namespace winrt::Microsoft::Terminal::Control::implementation
return { width, height };
}
// Function Description:
// - Calculates new dimensions (in pixels) from row and column counts.
// Arguments:
// - dpi: The dpi value.
// - sizeInChars: The size to get the new dimensions for.
// Return Value:
// - a size containing the requested dimensions in pixels.
winrt::Windows::Foundation::Size TermControl::GetNewDimensions(const winrt::Windows::Foundation::Size& sizeInChars)
{
const auto cols = ::base::saturated_cast<int32_t>(sizeInChars.Width);
const auto rows = ::base::saturated_cast<int32_t>(sizeInChars.Height);
const auto fontSize = _core.FontSize();
const auto scrollState = _core.Settings().ScrollState();
const auto padding = _core.Settings().Padding();
const auto scale = static_cast<float>(DisplayInformation::GetForCurrentView().RawPixelsPerViewPixel());
float width = cols * static_cast<float>(fontSize.Width);
float height = rows * static_cast<float>(fontSize.Height);
// Reserve additional space if scrollbar is intended to be visible
if (scrollState != ScrollbarState::Hidden)
{
// UWP XAML scrollbars aren't guaranteed to be the same size as the
// ComCtl scrollbars, but it's certainly close enough.
const auto dpi = ::base::saturated_cast<uint32_t>(USER_DEFAULT_SCREEN_DPI * scale);
const auto scrollbarSize = GetSystemMetricsForDpi(SM_CXVSCROLL, dpi);
width += scrollbarSize;
}
const auto thickness = ParseThicknessFromPadding(padding);
// GH#2061 - make sure to account for the size the padding _will be_ scaled to
width += scale * static_cast<float>(thickness.Left + thickness.Right);
height += scale * static_cast<float>(thickness.Top + thickness.Bottom);
return { width, height };
}
// Method Description:
// - Get the size of a single character of this control. The size is in
// _pixels_. If you want it in DIPs, you'll need to DIVIDE by the
@ -4088,6 +4125,20 @@ namespace winrt::Microsoft::Terminal::Control::implementation
SearchMissingCommand.raise(*this, args);
}
winrt::fire_and_forget TermControl::_bubbleWindowSizeChanged(const IInspectable& /*sender*/, Control::WindowSizeChangedEventArgs args)
{
auto weakThis{ get_weak() };
co_await wil::resume_foreground(Dispatcher());
if (auto control{ weakThis.get() })
{
winrt::Windows::Foundation::Size cellCount{ static_cast<float>(args.Width()), static_cast<float>(args.Height()) };
const auto pixelSize = GetNewDimensions(cellCount);
WindowSizeChanged.raise(*this, winrt::make<implementation::WindowSizeChangedEventArgs>(static_cast<int32_t>(pixelSize.Width), static_cast<int32_t>(pixelSize.Height)));
}
}
til::CoordType TermControl::_calculateSearchScrollOffset() const
{
auto result = 0;

View File

@ -159,6 +159,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation
int32_t commandlineRows);
static Windows::Foundation::Size GetProposedDimensions(const IControlSettings& settings, const uint32_t dpi, const winrt::Windows::Foundation::Size& initialSizeInChars);
winrt::Windows::Foundation::Size GetNewDimensions(const winrt::Windows::Foundation::Size& initialSizeInChars);
void BellLightOn();
bool ReadOnly() const noexcept;
@ -211,6 +213,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
til::typed_event<IInspectable, Control::CharSentEventArgs> CharSent;
til::typed_event<IInspectable, Control::StringSentEventArgs> StringSent;
til::typed_event<IInspectable, Control::SearchMissingCommandEventArgs> SearchMissingCommand;
til::typed_event<IInspectable, Control::WindowSizeChangedEventArgs> WindowSizeChanged;
// UNDER NO CIRCUMSTANCES SHOULD YOU ADD A (PROJECTED_)FORWARDED_TYPED_EVENT HERE
// Those attach the handler to the core directly, and will explode if
@ -437,6 +440,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
void _showContextMenuAt(const til::point& controlRelativePos);
void _bubbleSearchMissingCommand(const IInspectable& sender, const Control::SearchMissingCommandEventArgs& args);
winrt::fire_and_forget _bubbleWindowSizeChanged(const IInspectable& sender, Control::WindowSizeChangedEventArgs args);
til::CoordType _calculateSearchScrollOffset() const;
void _PasteCommandHandler(const IInspectable& sender, const IInspectable& args);
@ -470,6 +474,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
Control::ControlCore::RestartTerminalRequested_revoker RestartTerminalRequested;
Control::ControlCore::SearchMissingCommand_revoker SearchMissingCommand;
Control::ControlCore::RefreshQuickFixUI_revoker RefreshQuickFixUI;
Control::ControlCore::WindowSizeChanged_revoker WindowSizeChanged;
// These are set up in _InitializeTerminal
Control::ControlCore::RendererWarning_revoker RendererWarning;

View File

@ -63,6 +63,7 @@ namespace Microsoft.Terminal.Control
event Windows.Foundation.TypedEventHandler<Object, Object> TabColorChanged;
event Windows.Foundation.TypedEventHandler<Object, Object> ReadOnlyChanged;
event Windows.Foundation.TypedEventHandler<Object, Object> FocusFollowMouseRequested;
event Windows.Foundation.TypedEventHandler<Object, WindowSizeChangedEventArgs> WindowSizeChanged;
event Windows.Foundation.TypedEventHandler<Object, CompletionsChangedEventArgs> CompletionsChanged;

View File

@ -1134,6 +1134,11 @@ void Terminal::SetShowWindowCallback(std::function<void(bool)> pfn) noexcept
_pfnShowWindowChanged.swap(pfn);
}
void Terminal::SetWindowSizeChangedCallback(std::function<void(int32_t, int32_t)> pfn) noexcept
{
_pfnWindowSizeChanged.swap(pfn);
}
// Method Description:
// - Allows setting a callback for playing MIDI notes.
// Arguments:

View File

@ -139,7 +139,7 @@ public:
void WarningBell() override;
void SetWindowTitle(const std::wstring_view title) override;
CursorType GetUserDefaultCursorStyle() const noexcept override;
bool ResizeWindow(const til::CoordType width, const til::CoordType height) noexcept override;
bool ResizeWindow(const til::CoordType width, const til::CoordType height) override;
void SetConsoleOutputCP(const unsigned int codepage) noexcept override;
unsigned int GetConsoleOutputCP() const noexcept override;
void CopyToClipboard(wil::zwstring_view content) override;
@ -232,6 +232,7 @@ public:
void CompletionsChangedCallback(std::function<void(std::wstring_view, unsigned int)> pfn) noexcept;
void SetSearchMissingCommandCallback(std::function<void(std::wstring_view, const til::CoordType)> pfn) noexcept;
void SetClearQuickFixCallback(std::function<void()> pfn) noexcept;
void SetWindowSizeChangedCallback(std::function<void(int32_t, int32_t)> pfn) noexcept;
void SetSearchHighlights(const std::vector<til::point_span>& highlights) noexcept;
void SetSearchHighlightFocused(const size_t focusedIdx, til::CoordType searchScrollOffset);
@ -344,6 +345,7 @@ private:
std::function<void(std::wstring_view, unsigned int)> _pfnCompletionsChanged;
std::function<void(std::wstring_view, const til::CoordType)> _pfnSearchMissingCommand;
std::function<void()> _pfnClearQuickFix;
std::function<void(int32_t, int32_t)> _pfnWindowSizeChanged;
RenderSettings _renderSettings;
std::unique_ptr<::Microsoft::Console::VirtualTerminal::StateMachine> _stateMachine;

View File

@ -97,9 +97,22 @@ CursorType Terminal::GetUserDefaultCursorStyle() const noexcept
return _defaultCursorShape;
}
bool Terminal::ResizeWindow(const til::CoordType /*width*/, const til::CoordType /*height*/) noexcept
bool Terminal::ResizeWindow(const til::CoordType width, const til::CoordType height)
{
// TODO: This will be needed to support various resizing sequences. See also GH#1860.
_assertLocked();
if (width <= 0 || height <= 0 || width > SHRT_MAX || height > SHRT_MAX)
{
return false;
}
if (_pfnWindowSizeChanged)
{
_pfnWindowSizeChanged(width, height);
return true;
}
return false;
}

View File

@ -388,6 +388,7 @@ void AppHost::Initialize()
_revokers.SetTaskbarProgress = _windowLogic.SetTaskbarProgress(winrt::auto_revoke, { this, &AppHost::SetTaskbarProgress });
_revokers.IdentifyWindowsRequested = _windowLogic.IdentifyWindowsRequested(winrt::auto_revoke, { this, &AppHost::_IdentifyWindowsRequested });
_revokers.RenameWindowRequested = _windowLogic.RenameWindowRequested(winrt::auto_revoke, { this, &AppHost::_RenameWindowRequested });
_revokers.WindowSizeChanged = _windowLogic.WindowSizeChanged(winrt::auto_revoke, { this, &AppHost::_WindowSizeChanged });
// A note: make sure to listen to our _window_'s settings changed, not the
// AppLogic's. We want to make sure the event has gone through the window
@ -725,6 +726,45 @@ void AppHost::_initialResizeAndRepositionWindow(const HWND hwnd, til::rect propo
LOG_LAST_ERROR_IF(!succeeded);
}
// Method Description:
// - Resize the window when window size changed signal is received.
// Arguments:
// - hwnd: The HWND of the window we're about to resize.
// - newSize: The new size of the window in pixels.
// Return Value:
// - None
void AppHost::_resizeWindow(const HWND hwnd, til::size newSize)
{
til::rect windowRect{ _window->GetWindowRect() };
UINT dpix = _window->GetCurrentDpi();
const auto islandWidth = Utils::ClampToShortMax(newSize.width, 1);
const auto islandHeight = Utils::ClampToShortMax(newSize.height, 1);
// 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) };
long adjustedWidth = islandWidth + nonClientSize.width;
long adjustedHeight = islandHeight + nonClientSize.height;
til::size dimensions{ Utils::ClampToShortMax(adjustedWidth, 1),
Utils::ClampToShortMax(adjustedHeight, 1) };
til::point origin{ windowRect.left, windowRect.top };
const til::rect newRect{ origin, dimensions };
bool succeeded = SetWindowPos(hwnd,
nullptr,
newRect.left,
newRect.top,
newRect.width(),
newRect.height(),
SWP_NOACTIVATE | SWP_NOZORDER);
// If we can't resize the window, that's really okay. We can just go on with
// the originally proposed window size.
LOG_LAST_ERROR_IF(!succeeded);
}
// Method Description:
// - Called when the app wants to set its titlebar content. We'll take the
// UIElement and set the Content property of our Titlebar that element.
@ -1224,6 +1264,12 @@ void AppHost::_ShowWindowChanged(const winrt::Windows::Foundation::IInspectable&
_showHideWindowThrottler->Run(args.ShowOrHide());
}
void AppHost::_WindowSizeChanged(const winrt::Windows::Foundation::IInspectable& /*sender*/,
const winrt::Microsoft::Terminal::Control::WindowSizeChangedEventArgs& args)
{
_resizeWindow(_window->GetHandle(), { args.Width(), args.Height() });
}
void AppHost::_SummonWindowRequested(const winrt::Windows::Foundation::IInspectable& sender,
const winrt::Windows::Foundation::IInspectable&)
{

View File

@ -134,6 +134,9 @@ private:
void _ShowWindowChanged(const winrt::Windows::Foundation::IInspectable& sender,
const winrt::Microsoft::Terminal::Control::ShowWindowArgs& args);
void _WindowSizeChanged(const winrt::Windows::Foundation::IInspectable& sender,
const winrt::Microsoft::Terminal::Control::WindowSizeChangedEventArgs& args);
void _updateTheme();
void _PropertyChangedHandler(const winrt::Windows::Foundation::IInspectable& sender,
@ -141,6 +144,8 @@ private:
void _initialResizeAndRepositionWindow(const HWND hwnd, til::rect proposedRect, winrt::Microsoft::Terminal::Settings::Model::LaunchMode& launchMode);
void _resizeWindow(const HWND hwnd, til::size newSize);
void _handleMoveContent(const winrt::Windows::Foundation::IInspectable& sender,
winrt::TerminalApp::RequestMoveContentArgs args);
void _handleAttach(const winrt::Windows::Foundation::IInspectable& sender,
@ -201,6 +206,7 @@ private:
winrt::TerminalApp::TerminalWindow::RequestLaunchPosition_revoker RequestLaunchPosition;
winrt::TerminalApp::TerminalWindow::PropertyChanged_revoker PropertyChanged;
winrt::TerminalApp::TerminalWindow::SettingsChanged_revoker SettingsChanged;
winrt::TerminalApp::TerminalWindow::WindowSizeChanged_revoker WindowSizeChanged;
winrt::Microsoft::Terminal::Remoting::Peasant::SendContentRequested_revoker SendContentRequested;
} _revokers{};

View File

@ -871,14 +871,15 @@ til::rect NonClientIslandWindow::GetNonClientFrame(UINT dpi) const noexcept
til::size NonClientIslandWindow::GetTotalNonClientExclusiveSize(UINT dpi) const noexcept
{
const auto islandFrame{ GetNonClientFrame(dpi) };
const auto scale = GetCurrentDpiScale();
// 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.
const auto titleBarHeight = _titlebar ? static_cast<LONG>(_titlebar.ActualHeight()) : 0;
const auto titleBarHeight = _titlebar ? static_cast<LONG>(_titlebar.ActualHeight()) * scale : 0;
return {
islandFrame.right - islandFrame.left,
islandFrame.bottom - islandFrame.top + titleBarHeight
islandFrame.bottom - islandFrame.top + static_cast<til::CoordType>(titleBarHeight)
};
}