WindowTests.cs 40 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163
  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. public class SizingTests : ScopedTestBase
  544. {
  545. [Fact]
  546. public void Child_Should_Be_Measured_With_Width_And_Height_If_SizeToContent_Is_Manual()
  547. {
  548. using (UnitTestApplication.Start(TestServices.StyledWindow))
  549. {
  550. var child = new ChildControl();
  551. var target = new Window
  552. {
  553. Width = 100,
  554. Height = 50,
  555. SizeToContent = SizeToContent.Manual,
  556. Content = child
  557. };
  558. // Verify that the child is initially measured with our Width/Height.
  559. Show(target);
  560. Assert.Equal(1, child.MeasureSizes.Count);
  561. Assert.Equal(new Size(100, 50), child.MeasureSizes[0]);
  562. // Now change the bounds: verify that we are using the new Width/Height, and not the old ClientSize.
  563. child.MeasureSizes.Clear();
  564. child.InvalidateMeasure();
  565. target.Width = 120;
  566. target.Height = 70;
  567. Dispatcher.UIThread.RunJobs();
  568. Assert.Equal(1, child.MeasureSizes.Count);
  569. Assert.Equal(new Size(120, 70), child.MeasureSizes[0]);
  570. }
  571. }
  572. [Fact]
  573. public void Child_Should_Be_Measured_With_ClientSize_If_SizeToContent_Is_Manual_And_No_Width_Height_Specified()
  574. {
  575. using (UnitTestApplication.Start(TestServices.StyledWindow))
  576. {
  577. var windowImpl = MockWindowingPlatform.CreateWindowMock();
  578. windowImpl.Setup(x => x.ClientSize).Returns(new Size(550, 450));
  579. var child = new ChildControl();
  580. var target = new Window(windowImpl.Object)
  581. {
  582. SizeToContent = SizeToContent.Manual,
  583. Content = child
  584. };
  585. Show(target);
  586. Assert.Equal(1, child.MeasureSizes.Count);
  587. Assert.Equal(new Size(550, 450), child.MeasureSizes[0]);
  588. }
  589. }
  590. [Fact]
  591. public void Child_Should_Be_Measured_With_MaxAutoSizeHint_If_SizeToContent_Is_WidthAndHeight()
  592. {
  593. using (UnitTestApplication.Start(TestServices.StyledWindow))
  594. {
  595. var windowImpl = MockWindowingPlatform.CreateWindowMock();
  596. windowImpl.Setup(x => x.MaxAutoSizeHint).Returns(new Size(1200, 1000));
  597. var child = new ChildControl();
  598. var target = new Window(windowImpl.Object)
  599. {
  600. Width = 100,
  601. Height = 50,
  602. SizeToContent = SizeToContent.WidthAndHeight,
  603. Content = child
  604. };
  605. target.Show();
  606. Assert.Equal(1, child.MeasureSizes.Count);
  607. Assert.Equal(new Size(1200, 1000), child.MeasureSizes[0]);
  608. }
  609. }
  610. [Fact]
  611. public void Should_Not_Have_Offset_On_Bounds_When_Content_Larger_Than_Max_Window_Size()
  612. {
  613. // Issue #3784.
  614. using (UnitTestApplication.Start(TestServices.StyledWindow))
  615. {
  616. var windowImpl = MockWindowingPlatform.CreateWindowMock();
  617. var clientSize = new Size(200, 200);
  618. var maxClientSize = new Size(480, 480);
  619. windowImpl.Setup(x => x.Resize(It.IsAny<Size>(), It.IsAny<WindowResizeReason>()))
  620. .Callback<Size, WindowResizeReason>((size, reason) =>
  621. {
  622. clientSize = size.Constrain(maxClientSize);
  623. windowImpl.Object.Resized?.Invoke(clientSize, reason);
  624. });
  625. windowImpl.Setup(x => x.ClientSize).Returns(() => clientSize);
  626. var child = new Canvas
  627. {
  628. Width = 400,
  629. Height = 800,
  630. };
  631. var target = new Window(windowImpl.Object)
  632. {
  633. SizeToContent = SizeToContent.WidthAndHeight,
  634. Content = child
  635. };
  636. Show(target);
  637. Assert.Equal(new Size(400, 480), target.Bounds.Size);
  638. // Issue #3784 causes this to be (0, 160) which makes no sense as Window has no
  639. // parent control to be offset against.
  640. Assert.Equal(new Point(0, 0), target.Bounds.Position);
  641. }
  642. }
  643. [Fact]
  644. public void Width_Height_Should_Not_Be_NaN_After_Show_With_SizeToContent_Manual()
  645. {
  646. using (UnitTestApplication.Start(TestServices.StyledWindow))
  647. {
  648. var child = new Canvas
  649. {
  650. Width = 400,
  651. Height = 800,
  652. };
  653. var target = new Window()
  654. {
  655. SizeToContent = SizeToContent.Manual,
  656. Content = child
  657. };
  658. Show(target);
  659. // Values come from MockWindowingPlatform defaults.
  660. Assert.Equal(800, target.Width);
  661. Assert.Equal(600, target.Height);
  662. }
  663. }
  664. [Fact]
  665. public void Width_Height_Should_Not_Be_NaN_After_Show_With_SizeToContent_WidthAndHeight()
  666. {
  667. using (UnitTestApplication.Start(TestServices.StyledWindow))
  668. {
  669. var child = new Canvas
  670. {
  671. Width = 400,
  672. Height = 800,
  673. };
  674. var target = new Window()
  675. {
  676. SizeToContent = SizeToContent.WidthAndHeight,
  677. Content = child
  678. };
  679. target.GetObservable(Window.WidthProperty).Subscribe(x => { });
  680. Show(target);
  681. Assert.Equal(400, target.Width);
  682. Assert.Equal(800, target.Height);
  683. }
  684. }
  685. [Fact]
  686. public void MaxWidth_And_MaxHeight_Should_Be_Respected_With_SizeToContent_WidthAndHeight()
  687. {
  688. using (UnitTestApplication.Start(TestServices.StyledWindow))
  689. {
  690. var child = new ChildControl();
  691. var target = new Window()
  692. {
  693. SizeToContent = SizeToContent.WidthAndHeight,
  694. MaxWidth = 300,
  695. MaxHeight = 700,
  696. Content = child,
  697. };
  698. Show(target);
  699. Assert.Equal(new[] { new Size(300, 700) }, child.MeasureSizes);
  700. }
  701. }
  702. [Fact]
  703. public void SizeToContent_Should_Not_Be_Lost_On_Show()
  704. {
  705. using (UnitTestApplication.Start(TestServices.StyledWindow))
  706. {
  707. var child = new Canvas
  708. {
  709. Width = 400,
  710. Height = 800,
  711. };
  712. var target = new Window()
  713. {
  714. SizeToContent = SizeToContent.WidthAndHeight,
  715. Content = child
  716. };
  717. Show(target);
  718. Assert.Equal(SizeToContent.WidthAndHeight, target.SizeToContent);
  719. }
  720. }
  721. [Fact]
  722. public void SizeToContent_Should_Not_Be_Lost_On_Scaling_Change()
  723. {
  724. using (UnitTestApplication.Start(TestServices.StyledWindow))
  725. {
  726. var child = new Canvas
  727. {
  728. Width = 209,
  729. Height = 117,
  730. };
  731. var target = new Window()
  732. {
  733. SizeToContent = SizeToContent.WidthAndHeight,
  734. Content = child
  735. };
  736. Show(target);
  737. // Size before and after DPI change is a real-world example, with size after DPI
  738. // change coming from Win32 WM_DPICHANGED.
  739. target.PlatformImpl.ScalingChanged(1.5);
  740. target.PlatformImpl.Resized(
  741. new Size(210.66666666666666, 118.66666666666667),
  742. WindowResizeReason.DpiChange);
  743. Assert.Equal(SizeToContent.WidthAndHeight, target.SizeToContent);
  744. }
  745. }
  746. [Fact]
  747. public void Width_Height_Should_Be_Updated_When_SizeToContent_Is_WidthAndHeight()
  748. {
  749. using (UnitTestApplication.Start(TestServices.StyledWindow))
  750. {
  751. var child = new Canvas
  752. {
  753. Width = 400,
  754. Height = 800,
  755. };
  756. var target = new Window()
  757. {
  758. SizeToContent = SizeToContent.WidthAndHeight,
  759. Content = child
  760. };
  761. Show(target);
  762. Assert.Equal(400, target.Width);
  763. Assert.Equal(800, target.Height);
  764. child.Width = 410;
  765. target.LayoutManager.ExecuteLayoutPass();
  766. Assert.Equal(410, target.Width);
  767. Assert.Equal(800, target.Height);
  768. Assert.Equal(SizeToContent.WidthAndHeight, target.SizeToContent);
  769. }
  770. }
  771. [Fact]
  772. public void Setting_Width_Should_Resize_WindowImpl()
  773. {
  774. // Issue #3796
  775. using (UnitTestApplication.Start(TestServices.StyledWindow))
  776. {
  777. var target = new Window()
  778. {
  779. Width = 400,
  780. Height = 800,
  781. };
  782. Show(target);
  783. Assert.Equal(400, target.Width);
  784. Assert.Equal(800, target.Height);
  785. target.Width = 410;
  786. target.LayoutManager.ExecuteLayoutPass();
  787. var windowImpl = Mock.Get(target.PlatformImpl);
  788. windowImpl.Verify(x => x.Resize(new Size(410, 800), WindowResizeReason.Application));
  789. Assert.Equal(410, target.Width);
  790. }
  791. }
  792. [Fact]
  793. public void User_Resize_Of_Window_Width_Should_Reset_SizeToContent()
  794. {
  795. using (UnitTestApplication.Start(TestServices.StyledWindow))
  796. {
  797. var target = new Window()
  798. {
  799. SizeToContent = SizeToContent.WidthAndHeight,
  800. Content = new Canvas
  801. {
  802. Width = 400,
  803. Height = 800,
  804. },
  805. };
  806. Show(target);
  807. Assert.Equal(400, target.Width);
  808. Assert.Equal(800, target.Height);
  809. target.PlatformImpl.Resized(new Size(410, 800), WindowResizeReason.User);
  810. Assert.Equal(410, target.Width);
  811. Assert.Equal(800, target.Height);
  812. Assert.Equal(SizeToContent.Height, target.SizeToContent);
  813. }
  814. }
  815. [Fact]
  816. public void User_Resize_Of_Window_Height_Should_Reset_SizeToContent()
  817. {
  818. using (UnitTestApplication.Start(TestServices.StyledWindow))
  819. {
  820. var target = new Window()
  821. {
  822. SizeToContent = SizeToContent.WidthAndHeight,
  823. Content = new Canvas
  824. {
  825. Width = 400,
  826. Height = 800,
  827. },
  828. };
  829. Show(target);
  830. Assert.Equal(400, target.Width);
  831. Assert.Equal(800, target.Height);
  832. target.PlatformImpl.Resized(new Size(400, 810), WindowResizeReason.User);
  833. Assert.Equal(400, target.Width);
  834. Assert.Equal(810, target.Height);
  835. Assert.Equal(SizeToContent.Width, target.SizeToContent);
  836. }
  837. }
  838. [Fact]
  839. public void Window_Resize_Should_Not_Reset_SizeToContent_If_CanResize_False()
  840. {
  841. using (UnitTestApplication.Start(TestServices.StyledWindow))
  842. {
  843. var target = new Window()
  844. {
  845. SizeToContent = SizeToContent.WidthAndHeight,
  846. CanResize = false,
  847. Content = new Canvas
  848. {
  849. Width = 400,
  850. Height = 800,
  851. },
  852. };
  853. Show(target);
  854. Assert.Equal(400, target.Width);
  855. Assert.Equal(800, target.Height);
  856. target.PlatformImpl.Resized(new Size(410, 810), WindowResizeReason.Unspecified);
  857. Assert.Equal(400, target.Width);
  858. Assert.Equal(800, target.Height);
  859. Assert.Equal(SizeToContent.WidthAndHeight, target.SizeToContent);
  860. }
  861. }
  862. [Fact]
  863. public void IsVisible_Should_Open_Window()
  864. {
  865. using (UnitTestApplication.Start(TestServices.StyledWindow))
  866. {
  867. var target = new Window();
  868. var raised = false;
  869. target.Opened += (s, e) => raised = true;
  870. target.IsVisible = true;
  871. Assert.True(raised);
  872. }
  873. }
  874. [Fact]
  875. public void Hiding_DialogWindow_Should_Complete_Task()
  876. {
  877. using (UnitTestApplication.Start(TestServices.StyledWindow))
  878. {
  879. var parent = new Window();
  880. parent.Show();
  881. var target = new Window();
  882. var task = target.ShowDialog<bool>(parent);
  883. target.IsVisible = false;
  884. Assert.True(task.IsCompletedSuccessfully);
  885. }
  886. }
  887. [Fact]
  888. public void Show_Works_When_Min_Dimension_Greater_Than_Max()
  889. {
  890. using var app = UnitTestApplication.Start(TestServices.StyledWindow);
  891. var target = new Window
  892. {
  893. MinWidth = 100,
  894. MaxWidth = 80,
  895. MinHeight = 200,
  896. MaxHeight = 180
  897. };
  898. Show(target);
  899. Assert.Equal(100, target.Width);
  900. Assert.Equal(200, target.Height);
  901. }
  902. protected virtual void Show(Window window)
  903. {
  904. window.Show();
  905. }
  906. }
  907. public class DialogSizingTests : SizingTests
  908. {
  909. protected override void Show(Window window)
  910. {
  911. var owner = new Window();
  912. owner.Show();
  913. window.ShowDialog(owner);
  914. }
  915. }
  916. private static Mock<IWindowImpl> CreateImpl()
  917. {
  918. var screen1 = new Mock<Screen>(1.75, new PixelRect(new PixelSize(1920, 1080)), new PixelRect(new PixelSize(1920, 966)), true);
  919. var screens = new Mock<IScreenImpl>();
  920. screens.Setup(x => x.ScreenFromWindow(It.IsAny<IWindowBaseImpl>())).Returns(screen1.Object);
  921. var windowImpl = new Mock<IWindowImpl>();
  922. windowImpl.Setup(r => r.Compositor).Returns(RendererMocks.CreateDummyCompositor());
  923. windowImpl.Setup(x => x.RenderScaling).Returns(1);
  924. windowImpl.Setup(x => x.TryGetFeature(It.Is<Type>(t => t == typeof(IScreenImpl)))).Returns(screens.Object);
  925. return windowImpl;
  926. }
  927. private class ChildControl : Control
  928. {
  929. public List<Size> MeasureSizes { get; } = new List<Size>();
  930. protected override Size MeasureOverride(Size availableSize)
  931. {
  932. MeasureSizes.Add(availableSize);
  933. return base.MeasureOverride(availableSize);
  934. }
  935. }
  936. private class TopmostWindow : Window
  937. {
  938. static TopmostWindow()
  939. {
  940. TopmostProperty.OverrideDefaultValue<TopmostWindow>(true);
  941. }
  942. }
  943. }
  944. }