Skip to content

Commit

Permalink
Fix window life cycle calls on tests (#14152) Fixes #14142 Fixes #7894
Browse files Browse the repository at this point in the history
  • Loading branch information
PureWeen committed Mar 23, 2023
1 parent 4bd4777 commit 186c644
Show file tree
Hide file tree
Showing 7 changed files with 134 additions and 18 deletions.
6 changes: 6 additions & 0 deletions src/Controls/tests/DeviceTests/ControlsHandlerTestBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@ await SetupWindowForTests<THandler>(window, async () =>
await OnLoadedAsync(content as VisualElement);
#if !WINDOWS
if (window is Window controlsWindow)
{
if (!controlsWindow.IsActivated)
Expand All @@ -174,6 +175,8 @@ await SetupWindowForTests<THandler>(window, async () =>
controlsWindow = null;
window.Activated();
}
#endif
#if WINDOWS
await Task.Delay(10);
#endif
Expand All @@ -187,6 +190,7 @@ await SetupWindowForTests<THandler>(window, async () =>
throw new Exception($"I can't work with {typeof(THandler)}");
#if !WINDOWS
bool isActivated = controlsWindow?.IsActivated ?? false;
bool isDestroyed = controlsWindow?.IsDestroyed ?? false;
Expand All @@ -195,6 +199,8 @@ await SetupWindowForTests<THandler>(window, async () =>
if (!isDestroyed)
window.Destroying();
#endif
}, mauiContext);
}
finally
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using Microsoft.Maui.DeviceTests.Stubs;
using Microsoft.Maui.Graphics.Win2D;
using Microsoft.Maui.Handlers;
using Microsoft.Maui.Hosting;
using Microsoft.Maui.Platform;
using Xunit;
using WPanel = Microsoft.UI.Xaml.Controls.Panel;
Expand Down Expand Up @@ -134,5 +135,41 @@ await CreateHandlerAndAddToWindow<WindowHandlerStub>(window, async (handler) =>
}
});
}

[Collection(ControlsHandlerTestBase.RunInNewWindowCollection)]
public class WindowTestsRunInNewWindowCollection : ControlsHandlerTestBase
{
[Fact]
public async Task MinimizeAndThenMaximizingWorks()
{
var window = new Window(new ContentPage());

int activated = 0;
int deactivated = 0;
int resumed = 0;

window.Activated += (_, _) => activated++;
window.Deactivated += (_, _) => deactivated++;
window.Resumed += (_, _) => resumed++;

await CreateHandlerAndAddToWindow<IWindowHandler>(window, async (handler) =>
{
var platformWindow = window.Handler.PlatformView as UI.Xaml.Window;
await Task.Yield();
for (int i = 0; i < 2; i++)
{
platformWindow.Restore();
await Task.Yield();
platformWindow.Minimize();
}
});

Assert.Equal(2, activated);
Assert.Equal(1, resumed);
Assert.Equal(2, deactivated);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -88,14 +88,17 @@ void OnClosed(object sender, UI.Xaml.WindowEventArgs args)

void OnActivated(object sender, UI.Xaml.WindowActivatedEventArgs args)
{
if (Window is not null)
if (args.WindowActivationState != UI.Xaml.WindowActivationState.Deactivated)
{
if (!Window.IsActivated)
if (Window is not null)
{
if (!Window.IsActivated)
_window.Activated();
}
else
{
_window.Activated();
}
else
{
_window.Activated();
}
}
}

Expand Down
12 changes: 6 additions & 6 deletions src/Core/src/Platform/Windows/ApplicationExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ public static void CreatePlatformWindow(this UI.Xaml.Application platformApplica
if (application.Handler?.MauiContext is not IMauiContext applicationContext)
return;

var winuiWndow = new MauiWinUIWindow();
var winuiWindow = new MauiWinUIWindow();

var mauiContext = applicationContext!.MakeWindowScope(winuiWndow, out var windowScope);
var mauiContext = applicationContext!.MakeWindowScope(winuiWindow, out var windowScope);

applicationContext.Services.InvokeLifecycleEvents<WindowsLifecycle.OnMauiContextCreated>(del => del(mauiContext));

Expand All @@ -25,11 +25,11 @@ public static void CreatePlatformWindow(this UI.Xaml.Application platformApplica

var window = application.CreateWindow(activationState);

winuiWndow.SetWindowHandler(window, mauiContext);
winuiWindow.SetWindowHandler(window, mauiContext);

applicationContext.Services.InvokeLifecycleEvents<WindowsLifecycle.OnWindowCreated>(del => del(winuiWndow));

winuiWndow.Activate();
applicationContext.Services.InvokeLifecycleEvents<WindowsLifecycle.OnWindowCreated>(del => del(winuiWindow));
winuiWindow.SetWindow(window);
winuiWindow.Activate();
}
}
}
38 changes: 32 additions & 6 deletions src/Core/src/Platform/Windows/MauiWinUIWindow.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ public class MauiWinUIWindow : UI.Xaml.Window, IPlatformSizeRestrictedWindow

IntPtr _windowIcon;
bool _enableResumeEvent;
bool _isActivated;
UI.Xaml.UIElement? _customTitleBar;

public MauiWinUIWindow()
Expand All @@ -42,13 +43,25 @@ protected virtual void OnActivated(object sender, UI.Xaml.WindowActivatedEventAr
{
if (args.WindowActivationState != UI.Xaml.WindowActivationState.Deactivated)
{
// We have to track isActivated calls because WinUI will call OnActivated Twice
// when maximizing a window
// https://github.com/microsoft/microsoft-ui-xaml/issues/7343
if (_isActivated)
return;

_isActivated = true;

if (_enableResumeEvent)
MauiWinUIApplication.Current.Services?.InvokeLifecycleEvents<WindowsLifecycle.OnResumed>(del => del(this));
Services?.InvokeLifecycleEvents<WindowsLifecycle.OnResumed>(del => del(this));
else
_enableResumeEvent = true;
}
else
{
_isActivated = false;
}

MauiWinUIApplication.Current.Services?.InvokeLifecycleEvents<WindowsLifecycle.OnActivated>(del => del(this, args));
Services?.InvokeLifecycleEvents<WindowsLifecycle.OnActivated>(del => del(this, args));
}

private void OnClosedPrivate(object sender, UI.Xaml.WindowEventArgs args)
Expand All @@ -60,23 +73,25 @@ private void OnClosedPrivate(object sender, UI.Xaml.WindowEventArgs args)
DestroyIcon(_windowIcon);
_windowIcon = IntPtr.Zero;
}

Window = null;
}

protected virtual void OnClosed(object sender, UI.Xaml.WindowEventArgs args)
{
MauiWinUIApplication.Current.Services?.InvokeLifecycleEvents<WindowsLifecycle.OnClosed>(del => del(this, args));
Services?.InvokeLifecycleEvents<WindowsLifecycle.OnClosed>(del => del(this, args));
}

protected virtual void OnVisibilityChanged(object sender, UI.Xaml.WindowVisibilityChangedEventArgs args)
{
MauiWinUIApplication.Current.Services?.InvokeLifecycleEvents<WindowsLifecycle.OnVisibilityChanged>(del => del(this, args));
Services?.InvokeLifecycleEvents<WindowsLifecycle.OnVisibilityChanged>(del => del(this, args));
}

public IntPtr WindowHandle => _windowManager.WindowHandle;

void SubClassingWin32()
{
MauiWinUIApplication.Current.Services?.InvokeLifecycleEvents<WindowsLifecycle.OnPlatformWindowSubclassed>(
Services?.InvokeLifecycleEvents<WindowsLifecycle.OnPlatformWindowSubclassed>(
del => del(this, new WindowsPlatformWindowSubclassedEventArgs(WindowHandle)));

_windowManager.WindowMessage += OnWindowMessage;
Expand Down Expand Up @@ -120,7 +135,7 @@ void OnWindowMessage(object? sender, WindowMessageEventArgs e)
}
}

MauiWinUIApplication.Current.Services?.InvokeLifecycleEvents<WindowsLifecycle.OnPlatformMessage>(
Services?.InvokeLifecycleEvents<WindowsLifecycle.OnPlatformMessage>(
m => m.Invoke(this, new WindowsPlatformMessageEventArgs(e.Hwnd, e.MessageId, e.WParam, e.LParam)));
}
}
Expand Down Expand Up @@ -153,6 +168,12 @@ void SetIcon()

SizeInt32 IPlatformSizeRestrictedWindow.MaximumSize { get; set; } = DefaultMaximumSize;

internal IWindow? Window { get; private set; }

internal IServiceProvider? Services =>
Window?.Handler?.GetServiceProvider() ??
MauiWinUIApplication.Current.Services;

internal UI.Xaml.UIElement? MauiCustomTitleBar
{
get => _customTitleBar;
Expand All @@ -178,6 +199,11 @@ internal void UpdateTitleOnCustomTitleBar()

[DllImport("user32.dll", SetLastError = true)]
static extern int DestroyIcon(IntPtr hIcon);

internal void SetWindow(IWindow window)
{
Window = window;
}
}

interface IPlatformSizeRestrictedWindow
Expand Down
24 changes: 24 additions & 0 deletions src/Core/src/Platform/Windows/WindowExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,9 @@ public static void UpdateMaximumSize(this UI.Xaml.Window platformWindow, IWindow
return window;
}

if (platformWindow is MauiWinUIWindow mauiWindow)
return mauiWindow?.Window;

return null;
}

Expand All @@ -198,6 +201,27 @@ public static float GetDisplayDensity(this UI.Xaml.Window platformWindow)
return PlatformMethods.GetDpiForWindow(hwnd) / DeviceDisplay.BaseLogicalDpi;
}

internal static void Minimize(this UI.Xaml.Window platformWindow)
{
PlatformMethods
.ShowWindow(platformWindow.GetWindowHandle(),
PlatformMethods.ShowWindowFlags.SW_MINIMIZE);
}

internal static void Maximize(this UI.Xaml.Window platformWindow)
{
PlatformMethods
.ShowWindow(platformWindow.GetWindowHandle(),
PlatformMethods.ShowWindowFlags.SW_MAXIMIZE);
}

internal static void Restore(this UI.Xaml.Window platformWindow)
{
PlatformMethods
.ShowWindow(platformWindow.GetWindowHandle(),
PlatformMethods.ShowWindowFlags.SW_RESTORE);
}

public static UI.Windowing.AppWindow? GetAppWindow(this UI.Xaml.Window platformWindow)
{
var hwnd = platformWindow.GetWindowHandle();
Expand Down
20 changes: 20 additions & 0 deletions src/Essentials/src/Platform/PlatformMethods.uwp.cs
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,9 @@ public static long GetWindowLongPtr(IntPtr hWnd, WindowLongFlags nIndex)
[DllImport("user32.dll")]
public static extern bool SetWindowPos(IntPtr hWnd, SpecialWindowHandles hWndInsertAfter, int x, int y, int width, int height, SetWindowPosFlags uFlags);

[DllImport("user32.dll")]
public static extern bool ShowWindow(IntPtr hWnd, ShowWindowFlags uFlags);

[DllImport("comctl32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr DefSubclassProc(IntPtr hWnd, uint uMsg, IntPtr wParam, IntPtr lParam);

Expand Down Expand Up @@ -145,6 +148,23 @@ public enum SetWindowPosFlags : uint
SWP_SHOWWINDOW = 0x0040,
}

[Flags]
public enum ShowWindowFlags : uint
{
SW_HIDE = 0,
SW_NORMAL = 1,
SW_SHOWMINIMIZED = 2,
SW_MAXIMIZE = 3,
SW_SHOWNOACTIVATE = 4,
SW_SHOW = 5,
SW_MINIMIZE = 6,
SW_SHOWMINNOACTIVE = 7,
SW_SHOWNA = 8,
SW_RESTORE = 9,
SW_SHOWDEFAULT = 10,
SW_FORCEMINIMIZE = 11,
}

[Flags]
public enum ExtendedWindowStyles : uint
{
Expand Down

0 comments on commit 186c644

Please sign in to comment.