ExtendClientAreaWindowTests.cs 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. using System;
  2. using System.Linq;
  3. using System.Threading.Tasks;
  4. using Avalonia.Controls;
  5. using Avalonia.Controls.Chrome;
  6. using Avalonia.Interactivity;
  7. using Avalonia.Media;
  8. using Avalonia.Platform;
  9. using Avalonia.VisualTree;
  10. using Xunit;
  11. namespace Avalonia.IntegrationTests.Win32;
  12. public abstract class ExtendClientAreaWindowTests : IDisposable
  13. {
  14. private const double ClientWidth = 200;
  15. private const double ClientHeight = 200;
  16. private Window? _window;
  17. private Window Window
  18. {
  19. get
  20. {
  21. Assert.NotNull(_window);
  22. return _window;
  23. }
  24. }
  25. protected abstract SystemDecorations Decorations { get; }
  26. public static MatrixTheoryData<bool, WindowState> States
  27. => new([true, false], Enum.GetValues<WindowState>());
  28. private async Task InitWindowAsync(WindowState state, bool canResize)
  29. {
  30. Assert.Null(_window);
  31. _window = new Window
  32. {
  33. CanResize = canResize,
  34. WindowState = state,
  35. SystemDecorations = Decorations,
  36. ExtendClientAreaToDecorationsHint = true,
  37. ExtendClientAreaChromeHints = ExtendClientAreaChromeHints.PreferSystemChrome,
  38. Width = ClientWidth,
  39. Height = ClientHeight,
  40. WindowStartupLocation = WindowStartupLocation.Manual,
  41. Position = new PixelPoint(50, 50),
  42. Content = new Border
  43. {
  44. Background = Brushes.DodgerBlue,
  45. BorderBrush = Brushes.Yellow,
  46. BorderThickness = new Thickness(1)
  47. }
  48. };
  49. _window.Show();
  50. await Window.WhenLoadedAsync();
  51. }
  52. [Theory]
  53. [MemberData(nameof(States))]
  54. public async Task Normal_State_Respects_Client_Size(bool canResize, WindowState initialState)
  55. {
  56. await InitWindowAsync(initialState, canResize);
  57. if (initialState != WindowState.Normal)
  58. Window.WindowState = WindowState.Normal;
  59. // The client size should have been kept
  60. var expected = PixelSize.FromSize(new Size(ClientWidth, ClientHeight), Window.RenderScaling);
  61. var clientSize = Window.GetWin32ClientSize();
  62. Assert.Equal(expected, clientSize);
  63. VerifyNormalState(canResize);
  64. }
  65. protected abstract void VerifyNormalState(bool canResize);
  66. [Theory]
  67. [MemberData(nameof(States))]
  68. public async Task Maximized_State_Fills_Screen_Working_Area(bool canResize, WindowState initialState)
  69. {
  70. await InitWindowAsync(initialState, canResize);
  71. if (initialState != WindowState.Maximized)
  72. Window.WindowState = WindowState.Maximized;
  73. // The client size should match the screen working area
  74. var clientSize = Window.GetWin32ClientSize();
  75. var screenWorkingArea = Window.GetScreen().WorkingArea;
  76. Assert.Equal(screenWorkingArea.Size, clientSize);
  77. VerifyMaximizedState();
  78. }
  79. protected abstract void VerifyMaximizedState();
  80. [Theory]
  81. [MemberData(nameof(States))]
  82. public async Task FullScreen_State_Fills_Screen(bool canResize, WindowState initialState)
  83. {
  84. await InitWindowAsync(initialState, canResize);
  85. if (initialState != WindowState.FullScreen)
  86. Window.WindowState = WindowState.FullScreen;
  87. // The client size should match the screen bounds
  88. var clientSize = Window.GetWin32ClientSize();
  89. var screenBounds = Window.GetScreen().Bounds;
  90. Assert.Equal(screenBounds.Width, clientSize.Width);
  91. Assert.Equal(screenBounds.Height, clientSize.Height);
  92. // The window size should also match the screen bounds
  93. var windowBounds = Window.GetWin32WindowBounds();
  94. Assert.Equal(screenBounds, windowBounds);
  95. // And no visible title bar
  96. AssertNoTitleBar();
  97. }
  98. protected void AssertHasBorder()
  99. {
  100. var clientSize = Window.GetWin32ClientSize();
  101. var windowBounds = Window.GetWin32WindowBounds();
  102. Assert.NotEqual(clientSize.Width, windowBounds.Width);
  103. Assert.NotEqual(clientSize.Height, windowBounds.Height);
  104. }
  105. protected void AssertNoBorder()
  106. {
  107. var clientSize = Window.GetWin32ClientSize();
  108. var windowBounds = Window.GetWin32WindowBounds();
  109. Assert.Equal(clientSize.Width, windowBounds.Width);
  110. Assert.Equal(clientSize.Height, windowBounds.Height);
  111. }
  112. protected (double TitleBarHeight, double ButtonsHeight) GetTitleBarInfo()
  113. {
  114. var titleBar = Window.GetVisualDescendants().OfType<TitleBar>().FirstOrDefault();
  115. Assert.NotNull(titleBar);
  116. var buttons = titleBar.GetVisualDescendants().OfType<CaptionButtons>().FirstOrDefault();
  117. Assert.NotNull(buttons);
  118. return (titleBar.Height, buttons.Height);
  119. }
  120. private void AssertNoTitleBar()
  121. {
  122. var (titleBarHeight, buttonsHeight) = GetTitleBarInfo();
  123. Assert.Equal(0, titleBarHeight);
  124. Assert.Equal(0, buttonsHeight);
  125. }
  126. public void Dispose()
  127. => _window?.Close();
  128. public sealed class DecorationsFull : ExtendClientAreaWindowTests
  129. {
  130. protected override SystemDecorations Decorations
  131. => SystemDecorations.Full;
  132. protected override void VerifyNormalState(bool canResize)
  133. {
  134. AssertHasBorder();
  135. AssertLargeTitleBarWithButtons();
  136. }
  137. protected override void VerifyMaximizedState()
  138. => AssertLargeTitleBarWithButtons();
  139. private void AssertLargeTitleBarWithButtons()
  140. {
  141. var (titleBarHeight, buttonsHeight) = GetTitleBarInfo();
  142. Assert.True(titleBarHeight > 20);
  143. Assert.True(buttonsHeight > 20);
  144. }
  145. }
  146. public sealed class DecorationsBorderOnly : ExtendClientAreaWindowTests
  147. {
  148. protected override SystemDecorations Decorations
  149. => SystemDecorations.BorderOnly;
  150. protected override void VerifyNormalState(bool canResize)
  151. {
  152. AssertHasBorder();
  153. if (canResize)
  154. AssertSmallTitleBarWithoutButtons();
  155. else
  156. AssertNoTitleBar();
  157. }
  158. protected override void VerifyMaximizedState()
  159. => AssertNoTitleBar();
  160. private void AssertSmallTitleBarWithoutButtons()
  161. {
  162. var (titleBarHeight, buttonsHeight) = GetTitleBarInfo();
  163. Assert.True(titleBarHeight < 10);
  164. Assert.NotEqual(0, titleBarHeight);
  165. Assert.Equal(0, buttonsHeight);
  166. }
  167. }
  168. public sealed class DecorationsNone : ExtendClientAreaWindowTests
  169. {
  170. protected override SystemDecorations Decorations
  171. => SystemDecorations.None;
  172. protected override void VerifyNormalState(bool canResize)
  173. {
  174. AssertNoBorder();
  175. AssertNoTitleBar();
  176. }
  177. protected override void VerifyMaximizedState()
  178. => AssertNoTitleBar();
  179. }
  180. }