@@ -34,10 +34,17 @@ NonClientIslandWindow::~NonClientIslandWindow()
3434{
3535}
3636
37- void NonClientIslandWindow::OnDragBarSizeChanged (winrt::Windows::Foundation::IInspectable sender, winrt::Windows::UI::Xaml::SizeChangedEventArgs eventArgs)
37+ // Method Description:
38+ // - Called when the app's size changes. When that happens, the size of the drag
39+ // bar may have changed. If it has, we'll need to update the WindowRgn of the
40+ // interop window.
41+ // Arguments:
42+ // - <unused>
43+ // Return Value:
44+ // - <none>
45+ void NonClientIslandWindow::OnDragBarSizeChanged (winrt::Windows::Foundation::IInspectable /* sender*/ , winrt::Windows::UI::Xaml::SizeChangedEventArgs /* eventArgs*/ )
3846{
39- InvalidateRect (NULL , NULL , TRUE );
40- ForceResize ();
47+ _UpdateDragRegion ();
4148}
4249
4350void NonClientIslandWindow::OnAppInitialized (winrt::TerminalApp::App app)
@@ -101,8 +108,6 @@ void NonClientIslandWindow::OnSize(const UINT width, const UINT height)
101108 const auto xPos = _isMaximized ? _maximizedMargins.cxLeftWidth : dragX;
102109 const auto yPos = _isMaximized ? _maximizedMargins.cyTopHeight : dragY;
103110
104- winrt::check_bool (SetWindowPos (_interopWindowHandle, HWND_BOTTOM, xPos, yPos, windowsWidth, windowsHeight, SWP_SHOWWINDOW));
105-
106111 if (_rootGrid)
107112 {
108113 winrt::Windows::Foundation::Size size{ (windowsWidth / scale) + 0 .5f , (windowsHeight / scale) + 0 .5f };
@@ -113,8 +118,53 @@ void NonClientIslandWindow::OnSize(const UINT width, const UINT height)
113118 _rootGrid.Arrange (finalRect);
114119 }
115120
121+ // I'm not sure that HWND_BOTTOM is any different than HWND_TOP for us.
122+ winrt::check_bool (SetWindowPos (_interopWindowHandle, HWND_BOTTOM, xPos, yPos, windowsWidth, windowsHeight, SWP_SHOWWINDOW));
123+ }
124+
125+ // Method Description:
126+ // - Update the region of our window that is the draggable area. This happens in
127+ // response to a OnDragBarSizeChanged event. We'll calculate the areas of the
128+ // window that we want to display XAML content in, and set the window region
129+ // of our child xaml-island window to that region. That way, the parent window
130+ // will still get NCHITTEST'ed _outside_ the XAML content area, for things
131+ // like dragging and resizing.
132+ // Arguments:
133+ // - <none>
134+ // Return Value:
135+ // - <none>
136+ void NonClientIslandWindow::_UpdateDragRegion ()
137+ {
116138 if (_dragBar)
117139 {
140+ // TODO:GH#1897 This is largely duplicated from OnSize, and we should do
141+ // better than that.
142+ const auto windowRect = GetWindowRect ();
143+ const auto width = windowRect.right - windowRect.left ;
144+ const auto height = windowRect.bottom - windowRect.top ;
145+
146+ const auto dpi = ::GetDpiForWindow (_window.get ());
147+
148+ const auto dragY = ::GetSystemMetricsForDpi (SM_CYDRAG, dpi);
149+ const auto dragX = ::GetSystemMetricsForDpi (SM_CXDRAG, dpi);
150+
151+ // If we're maximized, we don't want to use the frame as our margins,
152+ // instead we want to use the margins from the maximization. If we included
153+ // the left&right sides of the frame in this calculation while maximized,
154+ // you' have a few pixels of the window border on the sides while maximized,
155+ // which most apps do not have.
156+ const auto bordersWidth = _isMaximized ?
157+ (_maximizedMargins.cxLeftWidth + _maximizedMargins.cxRightWidth ) :
158+ (dragX * 2 );
159+ const auto bordersHeight = _isMaximized ?
160+ (_maximizedMargins.cyBottomHeight + _maximizedMargins.cyTopHeight ) :
161+ (dragY * 2 );
162+
163+ const auto windowsWidth = width - bordersWidth;
164+ const auto windowsHeight = height - bordersHeight;
165+ const auto xPos = _isMaximized ? _maximizedMargins.cxLeftWidth : dragX;
166+ const auto yPos = _isMaximized ? _maximizedMargins.cyTopHeight : dragY;
167+
118168 const auto dragBarRect = GetDragAreaRect ();
119169 const auto nonClientHeight = dragBarRect.bottom - dragBarRect.top ;
120170
@@ -128,8 +178,6 @@ void NonClientIslandWindow::OnSize(const UINT width, const UINT height)
128178 winrt::check_bool (CombineRgn (_dragBarRegion.get (), nonClientRegion.get (), clientRegion.get (), RGN_OR));
129179 winrt::check_bool (SetWindowRgn (_interopWindowHandle, _dragBarRegion.get (), true ));
130180 }
131-
132- winrt::check_hresult (_UpdateFrameMargins ());
133181}
134182
135183// Method Description:
@@ -229,10 +277,13 @@ MARGINS NonClientIslandWindow::GetFrameMargins() const noexcept
229277// - the HRESULT returned by DwmExtendFrameIntoClientArea.
230278[[nodiscard]] HRESULT NonClientIslandWindow::_UpdateFrameMargins () const noexcept
231279{
232- // Get the size of the borders we want to use. The sides and bottom will
233- // just be big enough for resizing, but the top will be as big as we need
234- // for the non-client content.
235- MARGINS margins = GetFrameMargins ();
280+ // Set frame margins with just a single pixel on the bottom. We don't
281+ // really want a window frame at all - we're drawing all of it. We
282+ // especially don't want a top margin - that's where the caption buttons
283+ // are, and we're drawing those. So just set a single pixel on the bottom,
284+ // because the method won't work with {0}.
285+ MARGINS margins = { 0 , 0 , 0 , 1 };
286+
236287 // Extend the frame into the client area.
237288 return DwmExtendFrameIntoClientArea (_window.get (), &margins);
238289}
@@ -386,29 +437,33 @@ RECT NonClientIslandWindow::GetMaxWindowRectInPixels(const RECT* const prcSugges
386437 }
387438 break ;
388439 }
440+
389441 case WM_EXITSIZEMOVE:
390442 {
391443 ForceResize ();
392444 break ;
393445 }
394- case WM_NCACTIVATE:
395- case WM_NCPAINT :
446+
447+ case WM_PAINT :
396448 {
397449 if (!_dragBar)
398450 {
399451 return 0 ;
400452 }
401453
402- const auto hdc = wil::GetDC (_window.get ());
454+ PAINTSTRUCT ps{ 0 };
455+ const auto hdc = wil::BeginPaint (_window.get (), &ps);
403456 if (hdc.get ())
404457 {
405458 const auto scale = GetCurrentDpiScale ();
406459 const auto dpi = ::GetDpiForWindow (_window.get ());
460+ // Get the dimensions of the drag borders for the sides of the window.
407461 const auto dragY = ::GetSystemMetricsForDpi (SM_CYDRAG, dpi);
408462 const auto dragX = ::GetSystemMetricsForDpi (SM_CXDRAG, dpi);
409463 const auto xPos = _isMaximized ? _maximizedMargins.cxLeftWidth : dragX;
410464 const auto yPos = _isMaximized ? _maximizedMargins.cyTopHeight : dragY;
411465
466+ // Create brush for borders, titlebar color.
412467 const auto backgroundBrush = _dragBar.Background ();
413468 const auto backgroundSolidBrush = backgroundBrush.as <winrt::Windows::UI::Xaml::Media::SolidColorBrush>();
414469 const auto backgroundColor = backgroundSolidBrush.Color ();
@@ -420,27 +475,34 @@ RECT NonClientIslandWindow::GetMaxWindowRectInPixels(const RECT* const prcSugges
420475 const auto cx = windowRect.right - windowRect.left ;
421476 const auto cy = windowRect.bottom - windowRect.top ;
422477
478+ // Fill in the _entire_ titlebar area.
479+ RECT dragBarRect = {};
480+ dragBarRect.left = xPos;
481+ dragBarRect.right = xPos + cx;
482+ dragBarRect.top = yPos;
483+ dragBarRect.bottom = yPos + cy;
484+ ::FillRect (hdc.get(), &dragBarRect, _backgroundBrush.get());
485+
486+ // Draw the top window border
423487 RECT clientRect = { 0 , 0 , cx, yPos };
424488 ::FillRect (hdc.get(), &clientRect, _backgroundBrush.get());
425489
490+ // Draw the left window border
426491 clientRect = { 0 , 0 , xPos, cy };
427492 ::FillRect (hdc.get(), &clientRect, _backgroundBrush.get());
428493
494+ // Draw the bottom window border
429495 clientRect = { 0 , cy - yPos, cx, cy };
430496 ::FillRect (hdc.get(), &clientRect, _backgroundBrush.get());
431497
498+ // Draw the right window border
432499 clientRect = { cx - xPos, 0 , cx, cy };
433500 ::FillRect (hdc.get(), &clientRect, _backgroundBrush.get());
434-
435- RECT dragBarRect = GetDragAreaRect ();
436- dragBarRect.left += xPos;
437- dragBarRect.right += xPos;
438- dragBarRect.bottom += yPos;
439- dragBarRect.top += yPos;
440- ::FillRect (hdc.get(), &dragBarRect, _backgroundBrush.get());
441501 }
502+
442503 return 0 ;
443504 }
505+
444506 case WM_LBUTTONDOWN:
445507 {
446508 POINT point1 = {};
0 commit comments