WindowTests.cs 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584
  1. using System;
  2. using System.Linq;
  3. using System.Runtime.InteropServices;
  4. using System.Threading;
  5. using Avalonia.Controls;
  6. using OpenQA.Selenium;
  7. using OpenQA.Selenium.Appium;
  8. using OpenQA.Selenium.Interactions;
  9. using SixLabors.ImageSharp.PixelFormats;
  10. using Xunit;
  11. using Xunit.Sdk;
  12. namespace Avalonia.IntegrationTests.Appium
  13. {
  14. [Collection("Default")]
  15. public class WindowTests : TestBase
  16. {
  17. public WindowTests(DefaultAppFixture fixture)
  18. : base(fixture, "Window")
  19. {
  20. }
  21. [Theory]
  22. [MemberData(nameof(StartupLocationData))]
  23. public void StartupLocation(Size? size, ShowWindowMode mode, WindowStartupLocation location, bool canResize)
  24. {
  25. using var window = OpenWindow(size, mode, location, canResize: canResize);
  26. var info = GetWindowInfo();
  27. if (size.HasValue)
  28. Assert.Equal(size.Value, info.ClientSize);
  29. Assert.True(info.FrameSize.Width >= info.ClientSize.Width, "Expected frame width >= client width.");
  30. Assert.True(info.FrameSize.Height > info.ClientSize.Height, "Expected frame height > client height.");
  31. var frameRect = new PixelRect(info.Position, PixelSize.FromSize(info.FrameSize, info.Scaling));
  32. switch (location)
  33. {
  34. case WindowStartupLocation.CenterScreen:
  35. {
  36. var expected = info.ScreenRect.CenterRect(frameRect);
  37. AssertCloseEnough(expected.Position, frameRect.Position);
  38. break;
  39. }
  40. case WindowStartupLocation.CenterOwner:
  41. {
  42. Assert.NotNull(info.OwnerRect);
  43. var expected = info.OwnerRect!.Value.CenterRect(frameRect);
  44. AssertCloseEnough(expected.Position, frameRect.Position);
  45. break;
  46. }
  47. }
  48. }
  49. [Theory]
  50. [MemberData(nameof(WindowStateData))]
  51. public void WindowState(Size? size, ShowWindowMode mode, WindowState state, bool canResize)
  52. {
  53. using var window = OpenWindow(size, mode, state: state, canResize: canResize);
  54. try
  55. {
  56. var info = GetWindowInfo();
  57. Assert.Equal(state, info.WindowState);
  58. switch (state)
  59. {
  60. case Controls.WindowState.Normal:
  61. Assert.True(info.FrameSize.Width * info.Scaling < info.ScreenRect.Size.Width);
  62. Assert.True(info.FrameSize.Height * info.Scaling < info.ScreenRect.Size.Height);
  63. break;
  64. case Controls.WindowState.Maximized:
  65. case Controls.WindowState.FullScreen:
  66. Assert.True(info.FrameSize.Width * info.Scaling >= info.ScreenRect.Size.Width);
  67. Assert.True(info.FrameSize.Height * info.Scaling >= info.ScreenRect.Size.Height);
  68. break;
  69. }
  70. }
  71. finally
  72. {
  73. if (state == Controls.WindowState.FullScreen)
  74. {
  75. try
  76. {
  77. Session.FindElementByAccessibilityId("CurrentWindowState").SendClick();
  78. Session.FindElementByAccessibilityId("WindowStateNormal").SendClick();
  79. // Wait for animations to run.
  80. if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
  81. Thread.Sleep(1000);
  82. }
  83. catch
  84. {
  85. /* Ignore errors in cleanup */
  86. }
  87. }
  88. }
  89. }
  90. [PlatformFact(TestPlatforms.Windows)]
  91. public void OnWindows_Docked_Windows_Retain_Size_Position_When_Restored()
  92. {
  93. using (OpenWindow(new Size(400, 400), ShowWindowMode.NonOwned, WindowStartupLocation.Manual))
  94. {
  95. var windowState = Session.FindElementByAccessibilityId("CurrentWindowState");
  96. Assert.Equal("Normal", windowState.GetComboBoxValue());
  97. var window = Session.FindElements(By.XPath("//Window")).First();
  98. new Actions(Session)
  99. .KeyDown(Keys.Meta)
  100. .SendKeys(Keys.Left)
  101. .KeyUp(Keys.Meta)
  102. .Perform();
  103. var original = GetWindowInfo();
  104. windowState.Click();
  105. Session.FindElementByName("Minimized").SendClick();
  106. new Actions(Session)
  107. .KeyDown(Keys.Alt)
  108. .SendKeys(Keys.Tab)
  109. .KeyUp(Keys.Alt)
  110. .Perform();
  111. var current = GetWindowInfo();
  112. Assert.Equal(original.Position, current.Position);
  113. Assert.Equal(original.FrameSize, current.FrameSize);
  114. }
  115. }
  116. [Fact]
  117. public void Showing_Window_With_Size_Larger_Than_Screen_Measures_Content_With_Working_Area()
  118. {
  119. using (OpenWindow(new Size(4000, 2200), ShowWindowMode.NonOwned, WindowStartupLocation.Manual))
  120. {
  121. var screenRectTextBox = Session.FindElementByAccessibilityId("CurrentClientSize");
  122. var measuredWithTextBlock = Session.FindElementByAccessibilityId("CurrentMeasuredWithText");
  123. var measuredWithString = measuredWithTextBlock.Text;
  124. var workingAreaString = screenRectTextBox.Text;
  125. var workingArea = Size.Parse(workingAreaString);
  126. var measuredWith = Size.Parse(measuredWithString);
  127. Assert.Equal(workingArea, measuredWith);
  128. }
  129. }
  130. [Theory]
  131. [InlineData(ShowWindowMode.NonOwned)]
  132. [InlineData(ShowWindowMode.Owned)]
  133. [InlineData(ShowWindowMode.Modal)]
  134. public void ShowMode(ShowWindowMode mode)
  135. {
  136. using var window = OpenWindow(null, mode, WindowStartupLocation.Manual);
  137. var windowState = Session.FindElementByAccessibilityId("CurrentWindowState");
  138. var original = GetWindowInfo();
  139. Assert.Equal("Normal", windowState.GetComboBoxValue());
  140. windowState.Click();
  141. Session.FindElementByAccessibilityId("WindowStateMaximized").SendClick();
  142. Assert.Equal("Maximized", windowState.GetComboBoxValue());
  143. windowState.Click();
  144. Session.FindElementByAccessibilityId("WindowStateNormal").SendClick();
  145. var current = GetWindowInfo();
  146. Assert.Equal(original.Position, current.Position);
  147. Assert.Equal(original.FrameSize, current.FrameSize);
  148. // On macOS, only non-owned windows can go fullscreen.
  149. if (!RuntimeInformation.IsOSPlatform(OSPlatform.OSX) || mode == ShowWindowMode.NonOwned)
  150. {
  151. windowState.Click();
  152. Session.FindElementByAccessibilityId("WindowStateFullScreen").SendClick();
  153. Assert.Equal("FullScreen", windowState.GetComboBoxValue());
  154. current = GetWindowInfo();
  155. var clientSize = PixelSize.FromSize(current.ClientSize, current.Scaling);
  156. Assert.True(clientSize.Width >= current.ScreenRect.Width);
  157. Assert.True(clientSize.Height >= current.ScreenRect.Height);
  158. windowState.SendClick();
  159. Session.FindElementByAccessibilityId("WindowStateNormal").SendClick();
  160. current = GetWindowInfo();
  161. Assert.Equal(original.Position, current.Position);
  162. Assert.Equal(original.FrameSize, current.FrameSize);
  163. }
  164. }
  165. [Fact]
  166. public void Extended_Client_Window_Shows_With_Requested_Size()
  167. {
  168. var clientSize = new Size(400, 400);
  169. using var window = OpenWindow(clientSize, ShowWindowMode.NonOwned, WindowStartupLocation.CenterScreen, extendClientArea: true);
  170. var windowState = Session.FindElementByAccessibilityId("CurrentWindowState");
  171. var current = GetWindowInfo();
  172. Assert.Equal(current.ClientSize, clientSize);
  173. }
  174. [Fact]
  175. public void TransparentWindow()
  176. {
  177. var showTransparentWindow = Session.FindElementByAccessibilityId("ShowTransparentWindow");
  178. showTransparentWindow.Click();
  179. Thread.Sleep(1000);
  180. var window = Session.FindElementByAccessibilityId("TransparentWindow");
  181. var screenshot = window.GetScreenshot();
  182. window.Click();
  183. var img = SixLabors.ImageSharp.Image.Load<Rgba32>(screenshot.AsByteArray);
  184. var topLeftColor = img[10, 10];
  185. var centerColor = img[img.Width / 2, img.Height / 2];
  186. Assert.Equal(new Rgba32(0, 128, 0), topLeftColor);
  187. Assert.Equal(new Rgba32(255, 0, 0), centerColor);
  188. }
  189. [Fact]
  190. public void TransparentPopup()
  191. {
  192. var showTransparentWindow = Session.FindElementByAccessibilityId("ShowTransparentPopup");
  193. showTransparentWindow.Click();
  194. Thread.Sleep(1000);
  195. var window = Session.FindElementByAccessibilityId("TransparentPopupBackground");
  196. var container = window.FindElementByAccessibilityId("PopupContainer");
  197. var screenshot = container.GetScreenshot();
  198. window.Click();
  199. var img = SixLabors.ImageSharp.Image.Load<Rgba32>(screenshot.AsByteArray);
  200. var topLeftColor = img[10, 10];
  201. var centerColor = img[img.Width / 2, img.Height / 2];
  202. Assert.Equal(new Rgba32(0, 128, 0), topLeftColor);
  203. Assert.Equal(new Rgba32(255, 0, 0), centerColor);
  204. }
  205. [PlatformFact(TestPlatforms.Windows)]
  206. public void Owned_Window_Should_Appear_Above_Topmost_Owner()
  207. {
  208. var showTopmostWindow = Session.FindElementByAccessibilityId("ShowTopmostWindow");
  209. using var window = showTopmostWindow.OpenWindowWithClick();
  210. Thread.Sleep(1000);
  211. var ownerWindow = Session.GetWindowById("OwnerWindow");
  212. var ownedWindow = Session.GetWindowById("OwnedWindow");
  213. Assert.NotNull(ownerWindow);
  214. Assert.NotNull(ownedWindow);
  215. var ownerPosition = GetPosition(ownerWindow);
  216. var ownedPosition = GetPosition(ownedWindow);
  217. // Owned Window moves
  218. var moveButton = ownedWindow.FindElementByAccessibilityId("MoveButton");
  219. moveButton.Click();
  220. Thread.Sleep(1000);
  221. Assert.Equal(GetPosition(ownerWindow), ownerPosition);
  222. Assert.NotEqual(GetPosition(ownedWindow), ownedPosition);
  223. PixelPoint GetPosition(AppiumWebElement window)
  224. {
  225. return PixelPoint.Parse(window.FindElementByAccessibilityId("CurrentPosition").Text);
  226. }
  227. }
  228. [Theory]
  229. [InlineData(ShowWindowMode.NonOwned, true)]
  230. [InlineData(ShowWindowMode.Owned, true)]
  231. [InlineData(ShowWindowMode.Modal, true)]
  232. [InlineData(ShowWindowMode.NonOwned, false)]
  233. [InlineData(ShowWindowMode.Owned, false)]
  234. [InlineData(ShowWindowMode.Modal, false)]
  235. public void Window_Has_Disabled_Maximize_Button_When_CanResize_Is_False(ShowWindowMode mode, bool extendClientArea)
  236. {
  237. using (OpenWindow(null, mode, WindowStartupLocation.Manual, canResize: false, extendClientArea: extendClientArea))
  238. {
  239. var secondaryWindow = Session.GetWindowById("SecondaryWindow");
  240. AppiumWebElement? maximizeButton;
  241. if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
  242. {
  243. maximizeButton = extendClientArea ?
  244. secondaryWindow.FindElementByXPath("//Button[@Name='Maximize']") :
  245. secondaryWindow.FindElementByXPath("//TitleBar/Button[2]");
  246. }
  247. else
  248. {
  249. maximizeButton = mode == ShowWindowMode.NonOwned ?
  250. secondaryWindow.FindElementByAccessibilityId("_XCUI:FullScreenWindow") :
  251. secondaryWindow.FindElementByAccessibilityId("_XCUI:ZoomWindow");
  252. }
  253. Assert.False(maximizeButton.Enabled);
  254. }
  255. }
  256. [Theory]
  257. [InlineData(false)]
  258. [InlineData(true)]
  259. public void Window_Minimize_Button_Enabled_Matches_CanMinimize(bool canMinimize)
  260. {
  261. using (OpenWindow(canMinimize: canMinimize))
  262. {
  263. var secondaryWindow = Session.GetWindowById("SecondaryWindow");
  264. var windowChrome = secondaryWindow.GetSystemChromeButtons();
  265. Assert.NotNull(windowChrome.Minimize);
  266. Assert.Equal(canMinimize, windowChrome.Minimize!.Enabled);
  267. }
  268. }
  269. [Theory]
  270. [InlineData(false)]
  271. [InlineData(true)]
  272. public void Window_Maximize_Button_Enabled_Matches_CanMaximize(bool canMaximize)
  273. {
  274. using (OpenWindow(canMaximize: canMaximize))
  275. {
  276. var secondaryWindow = Session.GetWindowById("SecondaryWindow");
  277. var windowChrome = secondaryWindow.GetSystemChromeButtons();
  278. var maximizeButton = windowChrome.FullScreen ?? windowChrome.Maximize;
  279. Assert.NotNull(maximizeButton);
  280. Assert.Equal(canMaximize, maximizeButton.Enabled);
  281. }
  282. }
  283. [Fact]
  284. public void Changing_SystemDecorations_Should_Not_Change_Frame_Size_And_Position()
  285. {
  286. using (OpenWindow(null, ShowWindowMode.NonOwned, WindowStartupLocation.Manual))
  287. {
  288. var info = GetWindowInfo();
  289. Session.FindElementByAccessibilityId("CurrentSystemDecorations").Click();
  290. Session.FindElementByAccessibilityId("SystemDecorationsNone").SendClick();
  291. var updatedInfo = GetWindowInfo();
  292. Assert.Equal(info.FrameSize, updatedInfo.FrameSize);
  293. Assert.Equal(info.Position, updatedInfo.Position);
  294. Session.FindElementByAccessibilityId("CurrentSystemDecorations").Click();
  295. Session.FindElementByAccessibilityId("SystemDecorationsFull").SendClick();
  296. updatedInfo = GetWindowInfo();
  297. Assert.Equal(info.FrameSize, updatedInfo.FrameSize);
  298. Assert.Equal(info.Position, updatedInfo.Position);
  299. }
  300. }
  301. [Fact]
  302. public void Changing_WindowState_Should_Not_Change_Frame_Size_And_Position()
  303. {
  304. using (OpenWindow())
  305. {
  306. var info = GetWindowInfo();
  307. Session.FindElementByAccessibilityId("CurrentWindowState").SendClick();
  308. Session.FindElementByAccessibilityId("WindowStateMaximized").SendClick();
  309. Session.FindElementByAccessibilityId("CurrentWindowState").SendClick();
  310. Session.FindElementByAccessibilityId("WindowStateNormal").SendClick();
  311. var updatedInfo = GetWindowInfo();
  312. Assert.Equal(info.FrameSize, updatedInfo.FrameSize);
  313. Assert.Equal(info.Position, updatedInfo.Position);
  314. }
  315. }
  316. [PlatformFact(TestPlatforms.Windows)]
  317. public void Changing_Size_Should_Not_Change_Position()
  318. {
  319. using (OpenWindow())
  320. {
  321. var info = GetWindowInfo();
  322. Session.FindElementByAccessibilityId("AddToWidth").SendClick();
  323. Session.FindElementByAccessibilityId("AddToHeight").SendClick();
  324. var updatedInfo = GetWindowInfo();
  325. Assert.Equal(info.Position, updatedInfo.Position);
  326. Assert.Equal(info.FrameSize
  327. .WithWidth(info.FrameSize.Width + 10)
  328. .WithHeight(info.FrameSize.Height + 10), updatedInfo.FrameSize);
  329. }
  330. }
  331. public static TheoryData<Size?, ShowWindowMode, WindowStartupLocation, bool> StartupLocationData()
  332. {
  333. var sizes = new Size?[] { null, new Size(400, 300) };
  334. var data = new TheoryData<Size?, ShowWindowMode, WindowStartupLocation, bool>();
  335. foreach (var size in sizes)
  336. {
  337. foreach (var mode in Enum.GetValues<ShowWindowMode>())
  338. {
  339. foreach (var location in Enum.GetValues<WindowStartupLocation>())
  340. {
  341. if (!(location == WindowStartupLocation.CenterOwner && mode == ShowWindowMode.NonOwned))
  342. {
  343. data.Add(size, mode, location, true);
  344. data.Add(size, mode, location, false);
  345. }
  346. }
  347. }
  348. }
  349. return data;
  350. }
  351. public static TheoryData<Size?, ShowWindowMode, WindowState, bool> WindowStateData()
  352. {
  353. var sizes = new Size?[] { null, new Size(400, 300) };
  354. var data = new TheoryData<Size?, ShowWindowMode, WindowState, bool>();
  355. foreach (var size in sizes)
  356. {
  357. foreach (var mode in Enum.GetValues<ShowWindowMode>())
  358. {
  359. foreach (var state in Enum.GetValues<WindowState>())
  360. {
  361. // Not sure how to handle testing minimized windows currently.
  362. if (state == Controls.WindowState.Minimized)
  363. continue;
  364. // Child/Modal windows cannot be fullscreen on macOS.
  365. if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX) &&
  366. state == Controls.WindowState.FullScreen &&
  367. mode != ShowWindowMode.NonOwned)
  368. continue;
  369. data.Add(size, mode, state, true);
  370. data.Add(size, mode, state, false);
  371. }
  372. }
  373. }
  374. return data;
  375. }
  376. private static void AssertCloseEnough(PixelPoint expected, PixelPoint actual)
  377. {
  378. if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
  379. {
  380. // On win32, accurate frame information cannot be obtained until a window is shown but
  381. // WindowStartupLocation needs to be calculated before the window is shown, meaning that
  382. // the position of a centered window can be off by a bit. From initial testing, looks
  383. // like this shouldn't be more than 10 pixels.
  384. if (Math.Abs(expected.X - actual.X) > 10)
  385. throw EqualException.ForMismatchedValues(expected, actual);
  386. if (Math.Abs(expected.Y - actual.Y) > 10)
  387. throw EqualException.ForMismatchedValues(expected, actual);
  388. }
  389. else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
  390. {
  391. if (Math.Abs(expected.X - actual.X) > 15)
  392. throw EqualException.ForMismatchedValues(expected, actual);
  393. if (Math.Abs(expected.Y - actual.Y) > 15)
  394. throw EqualException.ForMismatchedValues(expected, actual);
  395. }
  396. else
  397. {
  398. Assert.Equal(expected, actual);
  399. }
  400. }
  401. private IDisposable OpenWindow(
  402. Size? size = null,
  403. ShowWindowMode mode = ShowWindowMode.NonOwned,
  404. WindowStartupLocation location = WindowStartupLocation.Manual,
  405. WindowState state = Controls.WindowState.Normal,
  406. bool canResize = true,
  407. bool extendClientArea = false,
  408. bool canMinimize = true,
  409. bool canMaximize = true)
  410. {
  411. var sizeTextBox = Session.FindElementByAccessibilityId("ShowWindowSize");
  412. var modeComboBox = Session.FindElementByAccessibilityId("ShowWindowMode");
  413. var locationComboBox = Session.FindElementByAccessibilityId("ShowWindowLocation");
  414. var stateComboBox = Session.FindElementByAccessibilityId("ShowWindowState");
  415. var canResizeCheckBox = Session.FindElementByAccessibilityId("ShowWindowCanResize");
  416. var canMinimizeCheckBox = Session.FindElementByAccessibilityId("ShowWindowCanMinimize");
  417. var canMaximizeCheckBox = Session.FindElementByAccessibilityId("ShowWindowCanMaximize");
  418. var showButton = Session.FindElementByAccessibilityId("ShowWindow");
  419. var extendClientAreaCheckBox = Session.FindElementByAccessibilityId("ShowWindowExtendClientAreaToDecorationsHint");
  420. if (size.HasValue)
  421. sizeTextBox.SendKeys($"{size.Value.Width}, {size.Value.Height}");
  422. if (modeComboBox.GetComboBoxValue() != mode.ToString())
  423. {
  424. modeComboBox.Click();
  425. Session.FindElementByName(mode.ToString()).SendClick();
  426. }
  427. if (locationComboBox.GetComboBoxValue() != location.ToString())
  428. {
  429. locationComboBox.Click();
  430. Session.FindElementByName(location.ToString()).SendClick();
  431. }
  432. if (stateComboBox.GetComboBoxValue() != state.ToString())
  433. {
  434. stateComboBox.Click();
  435. Session.FindElementByAccessibilityId($"ShowWindowState{state}").SendClick();
  436. }
  437. if (canResizeCheckBox.GetIsChecked() != canResize)
  438. canResizeCheckBox.Click();
  439. if (canMinimizeCheckBox.GetIsChecked() != canMinimize)
  440. canMinimizeCheckBox.Click();
  441. if (canMaximizeCheckBox.GetIsChecked() != canMaximize)
  442. canMaximizeCheckBox.Click();
  443. if (extendClientAreaCheckBox.GetIsChecked() != extendClientArea)
  444. extendClientAreaCheckBox.Click();
  445. return showButton.OpenWindowWithClick();
  446. }
  447. private WindowInfo GetWindowInfo()
  448. {
  449. PixelRect? ReadOwnerRect()
  450. {
  451. var text = Session.FindElementByAccessibilityId("CurrentOwnerRect").Text;
  452. return !string.IsNullOrWhiteSpace(text) ? PixelRect.Parse(text) : null;
  453. }
  454. var retry = 0;
  455. for (;;)
  456. {
  457. try
  458. {
  459. return new(
  460. Size.Parse(Session.FindElementByAccessibilityId("CurrentClientSize").Text),
  461. Size.Parse(Session.FindElementByAccessibilityId("CurrentFrameSize").Text),
  462. PixelPoint.Parse(Session.FindElementByAccessibilityId("CurrentPosition").Text),
  463. ReadOwnerRect(),
  464. PixelRect.Parse(Session.FindElementByAccessibilityId("CurrentScreenRect").Text),
  465. double.Parse(Session.FindElementByAccessibilityId("CurrentScaling").Text),
  466. Enum.Parse<WindowState>(Session.FindElementByAccessibilityId("CurrentWindowState").Text));
  467. }
  468. catch (OpenQA.Selenium.NoSuchElementException) when (retry++ < 3)
  469. {
  470. // MacOS sometimes seems to need a bit of time to get itself back in order after switching out
  471. // of fullscreen.
  472. Thread.Sleep(1000);
  473. }
  474. }
  475. }
  476. public enum ShowWindowMode
  477. {
  478. NonOwned,
  479. Owned,
  480. Modal
  481. }
  482. private record WindowInfo(
  483. Size ClientSize,
  484. Size FrameSize,
  485. PixelPoint Position,
  486. PixelRect? OwnerRect,
  487. PixelRect ScreenRect,
  488. double Scaling,
  489. WindowState WindowState);
  490. }
  491. }