dotnet / wpf

WPF is a .NET Core UI framework for building Windows desktop applications.
MIT License
7.08k stars 1.17k forks source link

Window.Close() does not close owned windows #6757

Open topsterde opened 2 years ago

topsterde commented 2 years ago

See: https://docs.microsoft.com/en-us/dotnet/api/system.windows.window.close?view=windowsdesktop-6.0 Closing a Window causes any windows that it owns to be closed

Actual behavior:

miloush commented 2 years ago

As much as I don't like what's happening here, I agree this is a WPF bug.

The ownership chain is MainWindow > Window1 > Window2 where the last two are shown using ShowDialog(). The repro is pulling a trick where Window1 enqueues an operation to close itself, which gets executed during the Window2 frame.

The issue is that when Window1 handles WM_CLOSE and decides to proceed with it, as per documentation:

By default, the DefWindowProc function calls the DestroyWindow function to destroy the window.

This results in the anticipated WM_DESTROY message, however, this comes with a caveat, as per documentation:

If the specified window is a parent or owner window, DestroyWindow automatically destroys the associated child or owned windows when it destroys the parent or owner window. The function first destroys child or owned windows, and then it destroys the parent or owner window.

So when Window1 closes, Window2 gets a surprise WM_DESTROY without any preceding WM_CLOSE. And WM_CLOSE is where stopping the modal frame happens. The same bit, i.e.

https://github.com/dotnet/wpf/blob/2564e40f77db66c4178b338dde16c64be98a601e/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Window.cs#L4257-L4262

should happen in WmDestroy too.

By the way, this repro also hits this codepath:

https://github.com/dotnet/wpf/blob/2564e40f77db66c4178b338dde16c64be98a601e/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Window.cs#L4343-L4346