Skip to content

Commit 3d71708

Browse files
Merge pull request #21497 from unoplatform/dev/mazi/maximize-win
2 parents 33159f1 + 49c2839 commit 3d71708

File tree

4 files changed

+138
-13
lines changed

4 files changed

+138
-13
lines changed

src/Uno.UI.Runtime.Skia.Win32/UI/Windowing/Win32WindowWrapper.OverlappedPresenter.cs

Lines changed: 36 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ namespace Uno.UI.Runtime.Skia.Win32;
1212

1313
internal partial class Win32WindowWrapper : INativeOverlappedPresenter
1414
{
15+
private OverlappedPresenterState? _pendingState;
16+
1517
protected override IDisposable ApplyFullScreenPresenter()
1618
{
1719
// The WasShown guards are so that if a call to ApplyFullScreenPresenter is made before
@@ -35,10 +37,7 @@ protected override IDisposable ApplyFullScreenPresenter()
3537

3638
protected override IDisposable ApplyOverlappedPresenter(OverlappedPresenter presenter)
3739
{
38-
if (WasShown)
39-
{
40-
presenter.SetNative(this);
41-
}
40+
presenter.SetNative(this);
4241
return base.ApplyOverlappedPresenter(presenter);
4342
}
4443

@@ -79,11 +78,41 @@ public void SetIsAlwaysOnTop(bool isAlwaysOnTop)
7978
}
8079
}
8180

82-
public void Maximize() => PInvoke.ShowWindow(_hwnd, SHOW_WINDOW_CMD.SW_MAXIMIZE);
81+
public void Maximize()
82+
{
83+
if (WasShown)
84+
{
85+
PInvoke.ShowWindow(_hwnd, SHOW_WINDOW_CMD.SW_MAXIMIZE);
86+
}
87+
else
88+
{
89+
_pendingState = OverlappedPresenterState.Maximized;
90+
}
91+
}
8392

84-
public void Minimize(bool activateWindow) => PInvoke.ShowWindow(_hwnd, activateWindow ? SHOW_WINDOW_CMD.SW_MINIMIZE : SHOW_WINDOW_CMD.SW_SHOWMINNOACTIVE);
93+
public void Minimize(bool activateWindow)
94+
{
95+
if (WasShown)
96+
{
97+
PInvoke.ShowWindow(_hwnd, activateWindow ? SHOW_WINDOW_CMD.SW_MINIMIZE : SHOW_WINDOW_CMD.SW_SHOWMINNOACTIVE);
98+
}
99+
else
100+
{
101+
_pendingState = OverlappedPresenterState.Minimized;
102+
}
103+
}
85104

86-
public void Restore(bool activateWindow) => PInvoke.ShowWindow(_hwnd, activateWindow ? SHOW_WINDOW_CMD.SW_SHOWNORMAL : SHOW_WINDOW_CMD.SW_SHOWNOACTIVATE);
105+
public void Restore(bool activateWindow)
106+
{
107+
if (WasShown)
108+
{
109+
PInvoke.ShowWindow(_hwnd, activateWindow ? SHOW_WINDOW_CMD.SW_SHOWNORMAL : SHOW_WINDOW_CMD.SW_SHOWNOACTIVATE);
110+
}
111+
else
112+
{
113+
_pendingState = OverlappedPresenterState.Restored;
114+
}
115+
}
87116

88117
public OverlappedPresenterState State
89118
{

src/Uno.UI.Runtime.Skia.Win32/UI/Xaml/Window/Win32WindowWrapper.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -379,6 +379,24 @@ protected override void ShowCore()
379379
SetWindowStyle(WINDOW_STYLE.WS_DLGFRAME, false);
380380
_ = PInvoke.ShowWindow(_hwnd, SHOW_WINDOW_CMD.SW_MAXIMIZE);
381381
}
382+
else if (Window?.AppWindow.Presenter is OverlappedPresenter overlappedPresenter)
383+
{
384+
switch (_pendingState)
385+
{
386+
case OverlappedPresenterState.Maximized:
387+
_ = PInvoke.ShowWindow(_hwnd, SHOW_WINDOW_CMD.SW_MAXIMIZE);
388+
break;
389+
case OverlappedPresenterState.Minimized:
390+
_ = PInvoke.ShowWindow(_hwnd, SHOW_WINDOW_CMD.SW_MINIMIZE);
391+
break;
392+
case OverlappedPresenterState.Restored:
393+
_ = PInvoke.ShowWindow(_hwnd, SHOW_WINDOW_CMD.SW_RESTORE);
394+
break;
395+
default:
396+
_ = PInvoke.ShowWindow(_hwnd, SHOW_WINDOW_CMD.SW_SHOWDEFAULT);
397+
break;
398+
}
399+
}
382400
else
383401
{
384402
PInvoke.ShowWindow(_hwnd, SHOW_WINDOW_CMD.SW_SHOWDEFAULT);

src/Uno.UI.RuntimeTests/Tests/Microsoft_UI_Windowing/Given_AppWindow.cs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
using System;
33
using System.Reflection;
44
using System.Threading.Tasks;
5+
using Combinatorial.MSTest;
6+
using AwesomeAssertions;
57
using Microsoft.UI.Windowing;
68
using Microsoft.UI.Xaml;
79
using Private.Infrastructure;
@@ -150,6 +152,38 @@ void OnChanged(AppWindow s, AppWindowChangedEventArgs e)
150152
}
151153
}
152154

155+
[TestMethod]
156+
[CombinatorialData]
157+
[GitHubWorkItem("https://github.com/unoplatform/uno/issues/21435")]
158+
[PlatformCondition(ConditionMode.Exclude, RuntimeTestPlatforms.SkiaX11 | RuntimeTestPlatforms.SkiaMacOS)] // Skia/X11 & macOS: Fail in CI (#21194)
159+
public async Task When_Change_Window_State_Before_Activate(OverlappedPresenterState state)
160+
{
161+
AssertPositioningAndSizingSupport();
162+
var newWindow = new Window();
163+
var appWindow = newWindow.AppWindow;
164+
var activated = false;
165+
try
166+
{
167+
var overlappedPresenter = (OverlappedPresenter)appWindow.Presenter;
168+
Action act = state switch
169+
{
170+
OverlappedPresenterState.Maximized => () => overlappedPresenter.Maximize(),
171+
OverlappedPresenterState.Minimized => () => overlappedPresenter.Minimize(),
172+
_ => () => overlappedPresenter.Restore()
173+
};
174+
act.Should().NotThrow();
175+
newWindow.Activated += (s, e) => activated = true;
176+
newWindow.Activate();
177+
await TestServices.WindowHelper.WaitFor(() => activated);
178+
Assert.AreEqual(state, overlappedPresenter.State);
179+
}
180+
finally
181+
{
182+
await TestServices.WindowHelper.WaitForIdle();
183+
await TestServices.RunOnUIThread(() => newWindow.Close());
184+
}
185+
}
186+
153187
private void AssertPositioningAndSizingSupport()
154188
{
155189
if (!OperatingSystem.IsLinux() &&

src/Uno.UWP/Microsoft/UI/Windowing/OverlappedPresenter.cs

Lines changed: 50 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
using System.ComponentModel;
2-
using System.Runtime.CompilerServices;
31
using Microsoft.UI.Windowing.Native;
42

53
namespace Microsoft.UI.Windowing;
@@ -16,6 +14,7 @@ public partial class OverlappedPresenter : AppWindowPresenter
1614
private bool _isAlwaysOnTop;
1715
private bool _hasBorder;
1816
private bool _hasTitleBar;
17+
private OverlappedPresenterState? _pendingState;
1918

2019
internal OverlappedPresenter() : base(AppWindowPresenterKind.Overlapped)
2120
{
@@ -77,13 +76,23 @@ public bool IsAlwaysOnTop
7776

7877
public bool HasTitleBar => _hasTitleBar;
7978

80-
public OverlappedPresenterState State => Native?.State ?? OverlappedPresenterState.Restored;
79+
public OverlappedPresenterState State => Native?.State ?? _pendingState ?? OverlappedPresenterState.Restored;
8180

8281
public static OverlappedPresenterState RequestedStartupState { get; } = OverlappedPresenterState.Restored;
8382

8483
public void Restore() => Restore(false);
8584

86-
public void Maximize() => Native.Maximize();
85+
public void Maximize()
86+
{
87+
if (Native is not null)
88+
{
89+
Native.Maximize();
90+
}
91+
else
92+
{
93+
_pendingState = OverlappedPresenterState.Maximized;
94+
}
95+
}
8796

8897
/// <summary>
8998
/// Minimizes the window that the presenter is applied to.
@@ -94,7 +103,17 @@ public bool IsAlwaysOnTop
94103
///
95104
/// </summary>
96105
/// <param name="activateWindow"></param>
97-
public void Minimize(bool activateWindow) => Native.Minimize(activateWindow);
106+
public void Minimize(bool activateWindow)
107+
{
108+
if (Native is not null)
109+
{
110+
Native.Minimize(activateWindow);
111+
}
112+
else
113+
{
114+
_pendingState = OverlappedPresenterState.Minimized;
115+
}
116+
}
98117

99118
/// <summary>
100119
/// Sets the border and title bar properties of the window.
@@ -108,7 +127,17 @@ public void SetBorderAndTitleBar(bool hasBorder, bool hasTitleBar)
108127
Native?.SetBorderAndTitleBar(hasBorder, hasTitleBar);
109128
}
110129

111-
public void Restore(bool activateWindow) => Native.Restore(activateWindow);
130+
public void Restore(bool activateWindow)
131+
{
132+
if (Native is not null)
133+
{
134+
Native.Restore(activateWindow);
135+
}
136+
else
137+
{
138+
_pendingState = OverlappedPresenterState.Restored;
139+
}
140+
}
112141

113142
/// <summary>
114143
/// Creates a new instance of OverlappedPresenter.
@@ -194,6 +223,21 @@ internal void SetNative(INativeOverlappedPresenter nativePresenter)
194223
Native.SetIsMaximizable(IsMaximizable);
195224
Native.SetIsAlwaysOnTop(IsAlwaysOnTop);
196225
Native.SetBorderAndTitleBar(HasBorder, HasTitleBar);
226+
227+
if (_pendingState is OverlappedPresenterState.Maximized)
228+
{
229+
Native.Maximize();
230+
}
231+
else if (_pendingState is OverlappedPresenterState.Minimized)
232+
{
233+
Native.Minimize(false);
234+
}
235+
else
236+
{
237+
Native.Restore(false);
238+
}
239+
240+
_pendingState = null;
197241
}
198242
}
199243
}

0 commit comments

Comments
 (0)