WindowTests.cs 41 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Threading.Tasks;
  4. using Avalonia.Media;
  5. using Avalonia.Platform;
  6. using Avalonia.Rendering;
  7. using Avalonia.Rendering.Composition;
  8. using Avalonia.Threading;
  9. using Avalonia.UnitTests;
  10. using Moq;
  11. using Xunit;
  12. namespace Avalonia.Controls.UnitTests
  13. {
  14. public class WindowTests : ScopedTestBase
  15. {
  16. [Fact]
  17. public void Setting_Title_Should_Set_Impl_Title()
  18. {
  19. var windowImpl = new Mock<IWindowImpl>();
  20. windowImpl.Setup(r => r.RenderScaling).Returns(1.0);
  21. windowImpl.Setup(r => r.Compositor).Returns(RendererMocks.CreateDummyCompositor());
  22. var windowingPlatform = new MockWindowingPlatform(() => windowImpl.Object);
  23. using (UnitTestApplication.Start(new TestServices(windowingPlatform: windowingPlatform)))
  24. {
  25. var target = new Window();
  26. target.Title = "Hello World";
  27. windowImpl.Verify(x => x.SetTitle("Hello World"));
  28. }
  29. }
  30. [Fact]
  31. public void IsVisible_Should_Initially_Be_False()
  32. {
  33. using (UnitTestApplication.Start(TestServices.MockWindowingPlatform))
  34. {
  35. var window = new Window();
  36. Assert.False(window.IsVisible);
  37. }
  38. }
  39. [Fact]
  40. public void IsVisible_Should_Be_True_After_Show()
  41. {
  42. using (UnitTestApplication.Start(TestServices.StyledWindow))
  43. {
  44. var window = new Window();
  45. window.Show();
  46. Assert.True(window.IsVisible);
  47. }
  48. }
  49. [Fact]
  50. public void IsVisible_Should_Be_True_After_ShowDialog()
  51. {
  52. using (UnitTestApplication.Start(TestServices.StyledWindow))
  53. {
  54. var parent = new Window();
  55. parent.Show();
  56. var window = new Window();
  57. var task = window.ShowDialog(parent);
  58. Assert.True(window.IsVisible);
  59. }
  60. }
  61. [Fact]
  62. public void IsVisible_Should_Be_False_After_Hide()
  63. {
  64. using (UnitTestApplication.Start(TestServices.StyledWindow))
  65. {
  66. var window = new Window();
  67. window.Show();
  68. window.Hide();
  69. Assert.False(window.IsVisible);
  70. }
  71. }
  72. [Fact]
  73. public void IsVisible_Should_Be_False_After_Close()
  74. {
  75. using (UnitTestApplication.Start(TestServices.StyledWindow))
  76. {
  77. var window = new Window();
  78. window.Show();
  79. window.Close();
  80. Assert.False(window.IsVisible);
  81. }
  82. }
  83. [Fact]
  84. public void IsVisible_Should_Be_False_After_Impl_Signals_Close()
  85. {
  86. var windowImpl = CreateImpl();
  87. windowImpl.SetupProperty(x => x.Closed);
  88. windowImpl.Setup(x => x.DesktopScaling).Returns(1);
  89. var services = TestServices.StyledWindow.With(
  90. windowingPlatform: new MockWindowingPlatform(() => windowImpl.Object));
  91. using (UnitTestApplication.Start(services))
  92. {
  93. var window = new Window();
  94. window.Show();
  95. Assert.True(window.IsVisible);
  96. windowImpl.Object.Closed();
  97. Assert.False(window.IsVisible);
  98. }
  99. }
  100. [Fact]
  101. public void Closing_Should_Only_Be_Invoked_Once()
  102. {
  103. using (UnitTestApplication.Start(TestServices.StyledWindow))
  104. {
  105. var window = new Window();
  106. var count = 0;
  107. window.Closing +=
  108. (sender, e) =>
  109. {
  110. count++;
  111. };
  112. window.Show();
  113. window.Close();
  114. Assert.Equal(1, count);
  115. }
  116. }
  117. [Theory]
  118. [InlineData(true)]
  119. [InlineData(false)]
  120. public void Child_windows_should_be_closed_before_parent(bool programmaticClose)
  121. {
  122. using (UnitTestApplication.Start(TestServices.StyledWindow))
  123. {
  124. var window = new Window();
  125. var child = new Window();
  126. int count = 0;
  127. int windowClosing = 0;
  128. int childClosing = 0;
  129. int windowClosed = 0;
  130. int childClosed = 0;
  131. window.Closing += (sender, e) =>
  132. {
  133. Assert.Equal(WindowCloseReason.WindowClosing, e.CloseReason);
  134. Assert.Equal(programmaticClose, e.IsProgrammatic);
  135. count++;
  136. windowClosing = count;
  137. };
  138. child.Closing += (sender, e) =>
  139. {
  140. Assert.Equal(WindowCloseReason.OwnerWindowClosing, e.CloseReason);
  141. Assert.Equal(programmaticClose, e.IsProgrammatic);
  142. count++;
  143. childClosing = count;
  144. };
  145. window.Closed += (sender, e) =>
  146. {
  147. count++;
  148. windowClosed = count;
  149. };
  150. child.Closed += (sender, e) =>
  151. {
  152. count++;
  153. childClosed = count;
  154. };
  155. window.Show();
  156. child.Show(window);
  157. if (programmaticClose)
  158. {
  159. window.Close();
  160. }
  161. else
  162. {
  163. var cancel = window.PlatformImpl.Closing(WindowCloseReason.WindowClosing);
  164. Assert.Equal(false, cancel);
  165. }
  166. Assert.Equal(2, windowClosing);
  167. Assert.Equal(1, childClosing);
  168. Assert.Equal(4, windowClosed);
  169. Assert.Equal(3, childClosed);
  170. }
  171. }
  172. [Theory]
  173. [InlineData(true)]
  174. [InlineData(false)]
  175. public void Child_windows_must_not_close_before_parent_has_chance_to_Cancel_OSCloseButton(bool programmaticClose)
  176. {
  177. using (UnitTestApplication.Start(TestServices.StyledWindow))
  178. {
  179. var window = new Window();
  180. var child = new Window();
  181. int count = 0;
  182. int windowClosing = 0;
  183. int childClosing = 0;
  184. int windowClosed = 0;
  185. int childClosed = 0;
  186. window.Closing += (sender, e) =>
  187. {
  188. count++;
  189. windowClosing = count;
  190. e.Cancel = true;
  191. };
  192. child.Closing += (sender, e) =>
  193. {
  194. count++;
  195. childClosing = count;
  196. };
  197. window.Closed += (sender, e) =>
  198. {
  199. count++;
  200. windowClosed = count;
  201. };
  202. child.Closed += (sender, e) =>
  203. {
  204. count++;
  205. childClosed = count;
  206. };
  207. window.Show();
  208. child.Show(window);
  209. if (programmaticClose)
  210. {
  211. window.Close();
  212. }
  213. else
  214. {
  215. var cancel = window.PlatformImpl.Closing(WindowCloseReason.WindowClosing);
  216. Assert.Equal(true, cancel);
  217. }
  218. Assert.Equal(2, windowClosing);
  219. Assert.Equal(1, childClosing);
  220. Assert.Equal(0, windowClosed);
  221. Assert.Equal(0, childClosed);
  222. }
  223. }
  224. [Fact]
  225. public void Showing_Should_Start_Renderer()
  226. {
  227. using (UnitTestApplication.Start(TestServices.StyledWindow))
  228. {
  229. var target = new Window(CreateImpl().Object);
  230. target.Show();
  231. Assert.True(MediaContext.Instance.IsTopLevelActive(target));
  232. }
  233. }
  234. [Fact]
  235. public void ShowDialog_Should_Start_Renderer()
  236. {
  237. using (UnitTestApplication.Start(TestServices.StyledWindow))
  238. {
  239. var parent = new Window();
  240. var target = new Window(CreateImpl().Object);
  241. parent.Show();
  242. target.ShowDialog<object>(parent);
  243. Assert.True(MediaContext.Instance.IsTopLevelActive(target));
  244. }
  245. }
  246. [Fact]
  247. public void ShowDialog_Should_Raise_Opened()
  248. {
  249. using (UnitTestApplication.Start(TestServices.StyledWindow))
  250. {
  251. var parent = new Window();
  252. var target = new Window();
  253. var raised = false;
  254. parent.Show();
  255. target.Opened += (s, e) => raised = true;
  256. target.ShowDialog<object>(parent);
  257. Assert.True(raised);
  258. }
  259. }
  260. [Fact]
  261. public void Hiding_Should_Stop_Renderer()
  262. {
  263. using (UnitTestApplication.Start(TestServices.StyledWindow))
  264. {
  265. var target = new Window(CreateImpl().Object);
  266. target.Show();
  267. target.Hide();
  268. Assert.False(MediaContext.Instance.IsTopLevelActive(target));
  269. }
  270. }
  271. [Fact]
  272. public async Task ShowDialog_With_ValueType_Returns_Default_When_Closed()
  273. {
  274. using (UnitTestApplication.Start(TestServices.StyledWindow))
  275. {
  276. var parent = new Window();
  277. var windowImpl = CreateImpl();
  278. windowImpl.Setup(x => x.Compositor).Returns(RendererMocks.CreateDummyCompositor());
  279. windowImpl.SetupProperty(x => x.Closed);
  280. windowImpl.Setup(x => x.DesktopScaling).Returns(1);
  281. windowImpl.Setup(x => x.RenderScaling).Returns(1);
  282. parent.Show();
  283. var target = new Window(windowImpl.Object);
  284. var task = target.ShowDialog<bool>(parent);
  285. windowImpl.Object.Closed();
  286. var result = await task;
  287. Assert.False(result);
  288. }
  289. }
  290. [Fact]
  291. public void Calling_Show_On_Closed_Window_Should_Throw()
  292. {
  293. using (UnitTestApplication.Start(TestServices.StyledWindow))
  294. {
  295. var target = new Window();
  296. target.Show();
  297. target.Close();
  298. var openedRaised = false;
  299. target.Opened += (s, e) => openedRaised = true;
  300. var ex = Assert.Throws<InvalidOperationException>(() => target.Show());
  301. Assert.Equal("Cannot re-show a closed window.", ex.Message);
  302. Assert.False(openedRaised);
  303. }
  304. }
  305. [Fact]
  306. public async Task Calling_ShowDialog_On_Closed_Window_Should_Throw()
  307. {
  308. using (UnitTestApplication.Start(TestServices.StyledWindow))
  309. {
  310. var parent = new Window();
  311. var windowImpl = CreateImpl();
  312. windowImpl.Setup(x => x.Compositor).Returns(RendererMocks.CreateDummyCompositor());
  313. windowImpl.SetupProperty(x => x.Closed);
  314. windowImpl.Setup(x => x.DesktopScaling).Returns(1);
  315. windowImpl.Setup(x => x.RenderScaling).Returns(1);
  316. parent.Show();
  317. var target = new Window(windowImpl.Object);
  318. var task = target.ShowDialog<bool>(parent);
  319. windowImpl.Object.Closed();
  320. await task;
  321. var openedRaised = false;
  322. target.Opened += (s, e) => openedRaised = true;
  323. var ex = await Assert.ThrowsAsync<InvalidOperationException>(() => target.ShowDialog<bool>(parent));
  324. Assert.Equal("Cannot re-show a closed window.", ex.Message);
  325. Assert.False(openedRaised);
  326. }
  327. }
  328. [Fact]
  329. public void Calling_Show_With_Closed_Parent_Window_Should_Throw()
  330. {
  331. using (UnitTestApplication.Start(TestServices.StyledWindow))
  332. {
  333. var parent = new Window();
  334. var target = new Window();
  335. parent.Close();
  336. var ex = Assert.Throws<InvalidOperationException>(() => target.Show(parent));
  337. Assert.Equal("Cannot show a window with a closed owner.", ex.Message);
  338. }
  339. }
  340. [Fact]
  341. public async Task Calling_ShowDialog_With_Closed_Parent_Window_Should_Throw()
  342. {
  343. using (UnitTestApplication.Start(TestServices.StyledWindow))
  344. {
  345. var parent = new Window();
  346. var target = new Window();
  347. parent.Close();
  348. var ex = await Assert.ThrowsAsync<InvalidOperationException>(() => target.ShowDialog(parent));
  349. Assert.Equal("Cannot show a window with a closed owner.", ex.Message);
  350. }
  351. }
  352. [Fact]
  353. public void Calling_Show_With_Invisible_Parent_Window_Should_Throw()
  354. {
  355. using (UnitTestApplication.Start(TestServices.StyledWindow))
  356. {
  357. var parent = new Window();
  358. var target = new Window();
  359. var ex = Assert.Throws<InvalidOperationException>(() => target.Show(parent));
  360. Assert.Equal("Cannot show window with non-visible owner.", ex.Message);
  361. }
  362. }
  363. [Fact]
  364. public async Task Calling_ShowDialog_With_Invisible_Parent_Window_Should_Throw()
  365. {
  366. using (UnitTestApplication.Start(TestServices.StyledWindow))
  367. {
  368. var parent = new Window();
  369. var target = new Window();
  370. var ex = await Assert.ThrowsAsync<InvalidOperationException>(() => target.ShowDialog(parent));
  371. Assert.Equal("Cannot show window with non-visible owner.", ex.Message);
  372. }
  373. }
  374. [Fact]
  375. public void Calling_Show_With_Self_As_Parent_Window_Should_Throw()
  376. {
  377. using (UnitTestApplication.Start(TestServices.StyledWindow))
  378. {
  379. var target = new Window();
  380. var ex = Assert.Throws<InvalidOperationException>(() => target.Show(target));
  381. Assert.Equal("A Window cannot be its own owner.", ex.Message);
  382. }
  383. }
  384. [Fact]
  385. public async Task Calling_ShowDialog_With_Self_As_Parent_Window_Should_Throw()
  386. {
  387. using (UnitTestApplication.Start(TestServices.StyledWindow))
  388. {
  389. var target = new Window();
  390. var ex = await Assert.ThrowsAsync<InvalidOperationException>(() => target.ShowDialog(target));
  391. Assert.Equal("A Window cannot be its own owner.", ex.Message);
  392. }
  393. }
  394. [Fact]
  395. public void Hiding_Parent_Window_Should_Close_Children()
  396. {
  397. using (UnitTestApplication.Start(TestServices.MockWindowingPlatform))
  398. {
  399. var parent = new Window();
  400. var child = new Window();
  401. parent.Show();
  402. child.Show(parent);
  403. parent.Hide();
  404. Assert.False(parent.IsVisible);
  405. Assert.False(child.IsVisible);
  406. }
  407. }
  408. [Fact]
  409. public void Hiding_Parent_Window_Should_Close_Dialog_Children()
  410. {
  411. using (UnitTestApplication.Start(TestServices.MockWindowingPlatform))
  412. {
  413. var parent = new Window();
  414. var child = new Window();
  415. parent.Show();
  416. child.ShowDialog(parent);
  417. parent.Hide();
  418. Assert.False(parent.IsVisible);
  419. Assert.False(child.IsVisible);
  420. }
  421. }
  422. [Fact]
  423. public void Window_Should_Not_Be_Centered_When_WindowStartupLocation_Is_CenterScreen_And_Window_Is_Hidden_And_Shown()
  424. {
  425. var screen1 = new Mock<Screen>(1.0, new PixelRect(new PixelSize(1920, 1080)), new PixelRect(new PixelSize(1920, 1040)), true);
  426. var screens = new Mock<IScreenImpl>();
  427. screens.Setup(x => x.AllScreens).Returns(new Screen[] { screen1.Object });
  428. screens.Setup(x => x.ScreenFromPoint(It.IsAny<PixelPoint>())).Returns(screen1.Object);
  429. var windowImpl = MockWindowingPlatform.CreateWindowMock();
  430. windowImpl.Setup(x => x.ClientSize).Returns(new Size(800, 480));
  431. windowImpl.Setup(x => x.DesktopScaling).Returns(1);
  432. windowImpl.Setup(x => x.RenderScaling).Returns(1);
  433. windowImpl.Setup(x => x.TryGetFeature(It.Is<Type>(t => t == typeof(IScreenImpl)))).Returns(screens.Object);
  434. using (UnitTestApplication.Start(TestServices.StyledWindow))
  435. {
  436. var window = new Window(windowImpl.Object)
  437. {
  438. WindowStartupLocation = WindowStartupLocation.CenterScreen
  439. };
  440. window.Show();
  441. var expected = new PixelPoint(150, 400);
  442. window.Position = expected;
  443. window.IsVisible = false;
  444. window.IsVisible = true;
  445. Assert.Equal(expected, window.Position);
  446. }
  447. }
  448. [Fact]
  449. public void Window_Should_Be_Centered_When_WindowStartupLocation_Is_CenterScreen()
  450. {
  451. var screen1 = new Mock<Screen>(1.0, new PixelRect(new PixelSize(1920, 1080)), new PixelRect(new PixelSize(1920, 1040)), true);
  452. var screen2 = new Mock<Screen>(1.0, new PixelRect(new PixelSize(1366, 768)), new PixelRect(new PixelSize(1366, 728)), false);
  453. var screens = new Mock<IScreenImpl>();
  454. screens.Setup(x => x.AllScreens).Returns(new Screen[] { screen1.Object, screen2.Object });
  455. screens.Setup(x => x.ScreenFromPoint(It.IsAny<PixelPoint>())).Returns(screen1.Object);
  456. var windowImpl = MockWindowingPlatform.CreateWindowMock();
  457. windowImpl.Setup(x => x.ClientSize).Returns(new Size(800, 480));
  458. windowImpl.Setup(x => x.DesktopScaling).Returns(1);
  459. windowImpl.Setup(x => x.RenderScaling).Returns(1);
  460. windowImpl.Setup(x => x.TryGetFeature(It.Is<Type>(t => t == typeof(IScreenImpl)))).Returns(screens.Object);
  461. using (UnitTestApplication.Start(TestServices.StyledWindow))
  462. {
  463. var window = new Window(windowImpl.Object);
  464. window.WindowStartupLocation = WindowStartupLocation.CenterScreen;
  465. window.Position = new PixelPoint(60, 40);
  466. window.Show();
  467. var expectedPosition = new PixelPoint(
  468. (int)(screen1.Object.WorkingArea.Size.Width / 2 - window.ClientSize.Width / 2),
  469. (int)(screen1.Object.WorkingArea.Size.Height / 2 - window.ClientSize.Height / 2));
  470. Assert.Equal(window.Position, expectedPosition);
  471. }
  472. }
  473. [Fact]
  474. public void Window_Should_Be_Sized_To_MinSize_If_InitialSize_Less_Than_MinSize()
  475. {
  476. var screen1 = new Mock<Screen>(1.75, new PixelRect(new PixelSize(1920, 1080)), new PixelRect(new PixelSize(1920, 966)), true);
  477. var screens = new Mock<IScreenImpl>();
  478. screens.Setup(x => x.AllScreens).Returns(new Screen[] { screen1.Object });
  479. screens.Setup(x => x.ScreenFromPoint(It.IsAny<PixelPoint>())).Returns(screen1.Object);
  480. var windowImpl = MockWindowingPlatform.CreateWindowMock(400, 300);
  481. windowImpl.Setup(x => x.DesktopScaling).Returns(1.75);
  482. windowImpl.Setup(x => x.RenderScaling).Returns(1.75);
  483. windowImpl.Setup(x => x.TryGetFeature(It.Is<Type>(t => t == typeof(IScreenImpl)))).Returns(screens.Object);
  484. using (UnitTestApplication.Start(TestServices.StyledWindow))
  485. {
  486. var window = new Window(windowImpl.Object);
  487. window.WindowStartupLocation = WindowStartupLocation.CenterScreen;
  488. window.MinWidth = 720;
  489. window.MinHeight = 480;
  490. window.Show();
  491. Assert.Equal(new PixelPoint(330, 63), window.Position);
  492. Assert.Equal(new Size(720, 480), window.Bounds.Size);
  493. }
  494. }
  495. [Fact]
  496. public void Window_Should_Be_Centered_Relative_To_Owner_When_WindowStartupLocation_Is_CenterOwner()
  497. {
  498. var parentWindowImpl = MockWindowingPlatform.CreateWindowMock();
  499. parentWindowImpl.Setup(x => x.ClientSize).Returns(new Size(800, 480));
  500. parentWindowImpl.Setup(x => x.MaxAutoSizeHint).Returns(new Size(1920, 1080));
  501. parentWindowImpl.Setup(x => x.DesktopScaling).Returns(1);
  502. parentWindowImpl.Setup(x => x.RenderScaling).Returns(1);
  503. var windowImpl = MockWindowingPlatform.CreateWindowMock();
  504. windowImpl.Setup(x => x.ClientSize).Returns(new Size(320, 200));
  505. windowImpl.Setup(x => x.MaxAutoSizeHint).Returns(new Size(1920, 1080));
  506. windowImpl.Setup(x => x.DesktopScaling).Returns(1);
  507. windowImpl.Setup(x => x.RenderScaling).Returns(1);
  508. var parentWindowServices = TestServices.StyledWindow.With(
  509. windowingPlatform: new MockWindowingPlatform(() => parentWindowImpl.Object));
  510. var windowServices = TestServices.StyledWindow.With(
  511. windowingPlatform: new MockWindowingPlatform(() => windowImpl.Object));
  512. using (UnitTestApplication.Start(parentWindowServices))
  513. {
  514. var parentWindow = new Window();
  515. parentWindow.Position = new PixelPoint(60, 40);
  516. parentWindow.Show();
  517. using (UnitTestApplication.Start(windowServices))
  518. {
  519. var window = new Window();
  520. window.WindowStartupLocation = WindowStartupLocation.CenterOwner;
  521. window.Position = new PixelPoint(60, 40);
  522. window.ShowDialog(parentWindow);
  523. var expectedPosition = new PixelPoint(
  524. (int)(parentWindow.Position.X + parentWindow.ClientSize.Width / 2 - window.ClientSize.Width / 2),
  525. (int)(parentWindow.Position.Y + parentWindow.ClientSize.Height / 2 - window.ClientSize.Height / 2));
  526. Assert.Equal(window.Position, expectedPosition);
  527. }
  528. }
  529. }
  530. [Fact]
  531. public void Window_Topmost_By_Default_Should_Configure_PlatformImpl_When_Constructed()
  532. {
  533. var windowImpl = MockWindowingPlatform.CreateWindowMock();
  534. var windowServices = TestServices.StyledWindow.With(
  535. windowingPlatform: new MockWindowingPlatform(() => windowImpl.Object));
  536. using (UnitTestApplication.Start(windowServices))
  537. {
  538. var window = new TopmostWindow();
  539. Assert.True(window.Topmost);
  540. windowImpl.Verify(i => i.SetTopmost(true));
  541. }
  542. }
  543. [Fact]
  544. public void CanMaximize_Should_Be_False_If_CanResize_Is_False()
  545. {
  546. var windowImpl = MockWindowingPlatform.CreateWindowMock();
  547. using var app = UnitTestApplication.Start(TestServices.StyledWindow.With(
  548. windowingPlatform: new MockWindowingPlatform(() => windowImpl.Object)));
  549. var window = new Window();
  550. Assert.True(window.CanMaximize);
  551. window.CanResize = false;
  552. Assert.False(window.CanMaximize);
  553. }
  554. public class SizingTests : ScopedTestBase
  555. {
  556. [Fact]
  557. public void Child_Should_Be_Measured_With_Width_And_Height_If_SizeToContent_Is_Manual()
  558. {
  559. using (UnitTestApplication.Start(TestServices.StyledWindow))
  560. {
  561. var child = new ChildControl();
  562. var target = new Window
  563. {
  564. Width = 100,
  565. Height = 50,
  566. SizeToContent = SizeToContent.Manual,
  567. Content = child
  568. };
  569. // Verify that the child is initially measured with our Width/Height.
  570. Show(target);
  571. Assert.Equal(1, child.MeasureSizes.Count);
  572. Assert.Equal(new Size(100, 50), child.MeasureSizes[0]);
  573. // Now change the bounds: verify that we are using the new Width/Height, and not the old ClientSize.
  574. child.MeasureSizes.Clear();
  575. child.InvalidateMeasure();
  576. target.Width = 120;
  577. target.Height = 70;
  578. Dispatcher.UIThread.RunJobs();
  579. Assert.Equal(1, child.MeasureSizes.Count);
  580. Assert.Equal(new Size(120, 70), child.MeasureSizes[0]);
  581. }
  582. }
  583. [Fact]
  584. public void Child_Should_Be_Measured_With_ClientSize_If_SizeToContent_Is_Manual_And_No_Width_Height_Specified()
  585. {
  586. using (UnitTestApplication.Start(TestServices.StyledWindow))
  587. {
  588. var windowImpl = MockWindowingPlatform.CreateWindowMock();
  589. windowImpl.Setup(x => x.ClientSize).Returns(new Size(550, 450));
  590. var child = new ChildControl();
  591. var target = new Window(windowImpl.Object)
  592. {
  593. SizeToContent = SizeToContent.Manual,
  594. Content = child
  595. };
  596. Show(target);
  597. Assert.Equal(1, child.MeasureSizes.Count);
  598. Assert.Equal(new Size(550, 450), child.MeasureSizes[0]);
  599. }
  600. }
  601. [Fact]
  602. public void Child_Should_Be_Measured_With_MaxAutoSizeHint_If_SizeToContent_Is_WidthAndHeight()
  603. {
  604. using (UnitTestApplication.Start(TestServices.StyledWindow))
  605. {
  606. var windowImpl = MockWindowingPlatform.CreateWindowMock();
  607. windowImpl.Setup(x => x.MaxAutoSizeHint).Returns(new Size(1200, 1000));
  608. var child = new ChildControl();
  609. var target = new Window(windowImpl.Object)
  610. {
  611. Width = 100,
  612. Height = 50,
  613. SizeToContent = SizeToContent.WidthAndHeight,
  614. Content = child
  615. };
  616. target.Show();
  617. Assert.Equal(1, child.MeasureSizes.Count);
  618. Assert.Equal(new Size(1200, 1000), child.MeasureSizes[0]);
  619. }
  620. }
  621. [Fact]
  622. public void Should_Not_Have_Offset_On_Bounds_When_Content_Larger_Than_Max_Window_Size()
  623. {
  624. // Issue #3784.
  625. using (UnitTestApplication.Start(TestServices.StyledWindow))
  626. {
  627. var windowImpl = MockWindowingPlatform.CreateWindowMock();
  628. var clientSize = new Size(200, 200);
  629. var maxClientSize = new Size(480, 480);
  630. windowImpl.Setup(x => x.Resize(It.IsAny<Size>(), It.IsAny<WindowResizeReason>()))
  631. .Callback<Size, WindowResizeReason>((size, reason) =>
  632. {
  633. clientSize = size.Constrain(maxClientSize);
  634. windowImpl.Object.Resized?.Invoke(clientSize, reason);
  635. });
  636. windowImpl.Setup(x => x.ClientSize).Returns(() => clientSize);
  637. var child = new Canvas
  638. {
  639. Width = 400,
  640. Height = 800,
  641. };
  642. var target = new Window(windowImpl.Object)
  643. {
  644. SizeToContent = SizeToContent.WidthAndHeight,
  645. Content = child
  646. };
  647. Show(target);
  648. Assert.Equal(new Size(400, 480), target.Bounds.Size);
  649. // Issue #3784 causes this to be (0, 160) which makes no sense as Window has no
  650. // parent control to be offset against.
  651. Assert.Equal(new Point(0, 0), target.Bounds.Position);
  652. }
  653. }
  654. [Fact]
  655. public void Width_Height_Should_Not_Be_NaN_After_Show_With_SizeToContent_Manual()
  656. {
  657. using (UnitTestApplication.Start(TestServices.StyledWindow))
  658. {
  659. var child = new Canvas
  660. {
  661. Width = 400,
  662. Height = 800,
  663. };
  664. var target = new Window()
  665. {
  666. SizeToContent = SizeToContent.Manual,
  667. Content = child
  668. };
  669. Show(target);
  670. // Values come from MockWindowingPlatform defaults.
  671. Assert.Equal(800, target.Width);
  672. Assert.Equal(600, target.Height);
  673. }
  674. }
  675. [Fact]
  676. public void Width_Height_Should_Not_Be_NaN_After_Show_With_SizeToContent_WidthAndHeight()
  677. {
  678. using (UnitTestApplication.Start(TestServices.StyledWindow))
  679. {
  680. var child = new Canvas
  681. {
  682. Width = 400,
  683. Height = 800,
  684. };
  685. var target = new Window()
  686. {
  687. SizeToContent = SizeToContent.WidthAndHeight,
  688. Content = child
  689. };
  690. target.GetObservable(Window.WidthProperty).Subscribe(x => { });
  691. Show(target);
  692. Assert.Equal(400, target.Width);
  693. Assert.Equal(800, target.Height);
  694. }
  695. }
  696. [Fact]
  697. public void MaxWidth_And_MaxHeight_Should_Be_Respected_With_SizeToContent_WidthAndHeight()
  698. {
  699. using (UnitTestApplication.Start(TestServices.StyledWindow))
  700. {
  701. var child = new ChildControl();
  702. var target = new Window()
  703. {
  704. SizeToContent = SizeToContent.WidthAndHeight,
  705. MaxWidth = 300,
  706. MaxHeight = 700,
  707. Content = child,
  708. };
  709. Show(target);
  710. Assert.Equal(new[] { new Size(300, 700) }, child.MeasureSizes);
  711. }
  712. }
  713. [Fact]
  714. public void SizeToContent_Should_Not_Be_Lost_On_Show()
  715. {
  716. using (UnitTestApplication.Start(TestServices.StyledWindow))
  717. {
  718. var child = new Canvas
  719. {
  720. Width = 400,
  721. Height = 800,
  722. };
  723. var target = new Window()
  724. {
  725. SizeToContent = SizeToContent.WidthAndHeight,
  726. Content = child
  727. };
  728. Show(target);
  729. Assert.Equal(SizeToContent.WidthAndHeight, target.SizeToContent);
  730. }
  731. }
  732. [Fact]
  733. public void SizeToContent_Should_Not_Be_Lost_On_Scaling_Change()
  734. {
  735. using (UnitTestApplication.Start(TestServices.StyledWindow))
  736. {
  737. var child = new Canvas
  738. {
  739. Width = 209,
  740. Height = 117,
  741. };
  742. var target = new Window()
  743. {
  744. SizeToContent = SizeToContent.WidthAndHeight,
  745. Content = child
  746. };
  747. Show(target);
  748. // Size before and after DPI change is a real-world example, with size after DPI
  749. // change coming from Win32 WM_DPICHANGED.
  750. target.PlatformImpl.ScalingChanged(1.5);
  751. target.PlatformImpl.Resized(
  752. new Size(210.66666666666666, 118.66666666666667),
  753. WindowResizeReason.DpiChange);
  754. Assert.Equal(SizeToContent.WidthAndHeight, target.SizeToContent);
  755. }
  756. }
  757. [Fact]
  758. public void Width_Height_Should_Be_Updated_When_SizeToContent_Is_WidthAndHeight()
  759. {
  760. using (UnitTestApplication.Start(TestServices.StyledWindow))
  761. {
  762. var child = new Canvas
  763. {
  764. Width = 400,
  765. Height = 800,
  766. };
  767. var target = new Window()
  768. {
  769. SizeToContent = SizeToContent.WidthAndHeight,
  770. Content = child
  771. };
  772. Show(target);
  773. Assert.Equal(400, target.Width);
  774. Assert.Equal(800, target.Height);
  775. child.Width = 410;
  776. target.LayoutManager.ExecuteLayoutPass();
  777. Assert.Equal(410, target.Width);
  778. Assert.Equal(800, target.Height);
  779. Assert.Equal(SizeToContent.WidthAndHeight, target.SizeToContent);
  780. }
  781. }
  782. [Fact]
  783. public void Setting_Width_Should_Resize_WindowImpl()
  784. {
  785. // Issue #3796
  786. using (UnitTestApplication.Start(TestServices.StyledWindow))
  787. {
  788. var target = new Window()
  789. {
  790. Width = 400,
  791. Height = 800,
  792. };
  793. Show(target);
  794. Assert.Equal(400, target.Width);
  795. Assert.Equal(800, target.Height);
  796. target.Width = 410;
  797. target.LayoutManager.ExecuteLayoutPass();
  798. var windowImpl = Mock.Get(target.PlatformImpl);
  799. windowImpl.Verify(x => x.Resize(new Size(410, 800), WindowResizeReason.Application));
  800. Assert.Equal(410, target.Width);
  801. }
  802. }
  803. [Fact]
  804. public void User_Resize_Of_Window_Width_Should_Reset_SizeToContent()
  805. {
  806. using (UnitTestApplication.Start(TestServices.StyledWindow))
  807. {
  808. var target = new Window()
  809. {
  810. SizeToContent = SizeToContent.WidthAndHeight,
  811. Content = new Canvas
  812. {
  813. Width = 400,
  814. Height = 800,
  815. },
  816. };
  817. Show(target);
  818. Assert.Equal(400, target.Width);
  819. Assert.Equal(800, target.Height);
  820. target.PlatformImpl.Resized(new Size(410, 800), WindowResizeReason.User);
  821. Assert.Equal(410, target.Width);
  822. Assert.Equal(800, target.Height);
  823. Assert.Equal(SizeToContent.Height, target.SizeToContent);
  824. }
  825. }
  826. [Fact]
  827. public void User_Resize_Of_Window_Height_Should_Reset_SizeToContent()
  828. {
  829. using (UnitTestApplication.Start(TestServices.StyledWindow))
  830. {
  831. var target = new Window()
  832. {
  833. SizeToContent = SizeToContent.WidthAndHeight,
  834. Content = new Canvas
  835. {
  836. Width = 400,
  837. Height = 800,
  838. },
  839. };
  840. Show(target);
  841. Assert.Equal(400, target.Width);
  842. Assert.Equal(800, target.Height);
  843. target.PlatformImpl.Resized(new Size(400, 810), WindowResizeReason.User);
  844. Assert.Equal(400, target.Width);
  845. Assert.Equal(810, target.Height);
  846. Assert.Equal(SizeToContent.Width, target.SizeToContent);
  847. }
  848. }
  849. [Fact]
  850. public void Window_Resize_Should_Not_Reset_SizeToContent_If_CanResize_False()
  851. {
  852. using (UnitTestApplication.Start(TestServices.StyledWindow))
  853. {
  854. var target = new Window()
  855. {
  856. SizeToContent = SizeToContent.WidthAndHeight,
  857. CanResize = false,
  858. Content = new Canvas
  859. {
  860. Width = 400,
  861. Height = 800,
  862. },
  863. };
  864. Show(target);
  865. Assert.Equal(400, target.Width);
  866. Assert.Equal(800, target.Height);
  867. target.PlatformImpl.Resized(new Size(410, 810), WindowResizeReason.Unspecified);
  868. Assert.Equal(400, target.Width);
  869. Assert.Equal(800, target.Height);
  870. Assert.Equal(SizeToContent.WidthAndHeight, target.SizeToContent);
  871. }
  872. }
  873. [Fact]
  874. public void IsVisible_Should_Open_Window()
  875. {
  876. using (UnitTestApplication.Start(TestServices.StyledWindow))
  877. {
  878. var target = new Window();
  879. var raised = false;
  880. target.Opened += (s, e) => raised = true;
  881. target.IsVisible = true;
  882. Assert.True(raised);
  883. }
  884. }
  885. [Fact]
  886. public void Hiding_DialogWindow_Should_Complete_Task()
  887. {
  888. using (UnitTestApplication.Start(TestServices.StyledWindow))
  889. {
  890. var parent = new Window();
  891. parent.Show();
  892. var target = new Window();
  893. var task = target.ShowDialog<bool>(parent);
  894. target.IsVisible = false;
  895. Assert.True(task.IsCompletedSuccessfully);
  896. }
  897. }
  898. [Fact]
  899. public void Show_Works_When_Min_Dimension_Greater_Than_Max()
  900. {
  901. using var app = UnitTestApplication.Start(TestServices.StyledWindow);
  902. var target = new Window
  903. {
  904. MinWidth = 100,
  905. MaxWidth = 80,
  906. MinHeight = 200,
  907. MaxHeight = 180
  908. };
  909. Show(target);
  910. Assert.Equal(100, target.Width);
  911. Assert.Equal(200, target.Height);
  912. }
  913. protected virtual void Show(Window window)
  914. {
  915. window.Show();
  916. }
  917. }
  918. public class DialogSizingTests : SizingTests
  919. {
  920. protected override void Show(Window window)
  921. {
  922. var owner = new Window();
  923. owner.Show();
  924. window.ShowDialog(owner);
  925. }
  926. }
  927. private static Mock<IWindowImpl> CreateImpl()
  928. {
  929. var screen1 = new Mock<Screen>(1.75, new PixelRect(new PixelSize(1920, 1080)), new PixelRect(new PixelSize(1920, 966)), true);
  930. var screens = new Mock<IScreenImpl>();
  931. screens.Setup(x => x.ScreenFromWindow(It.IsAny<IWindowBaseImpl>())).Returns(screen1.Object);
  932. var windowImpl = new Mock<IWindowImpl>();
  933. windowImpl.Setup(r => r.Compositor).Returns(RendererMocks.CreateDummyCompositor());
  934. windowImpl.Setup(x => x.RenderScaling).Returns(1);
  935. windowImpl.Setup(x => x.TryGetFeature(It.Is<Type>(t => t == typeof(IScreenImpl)))).Returns(screens.Object);
  936. return windowImpl;
  937. }
  938. private class ChildControl : Control
  939. {
  940. public List<Size> MeasureSizes { get; } = new List<Size>();
  941. protected override Size MeasureOverride(Size availableSize)
  942. {
  943. MeasureSizes.Add(availableSize);
  944. return base.MeasureOverride(availableSize);
  945. }
  946. }
  947. private class TopmostWindow : Window
  948. {
  949. static TopmostWindow()
  950. {
  951. TopmostProperty.OverrideDefaultValue<TopmostWindow>(true);
  952. }
  953. }
  954. }
  955. }