PyWebWinUI3 1.2.2__tar.gz → 1.2.4__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (130) hide show
  1. {pywebwinui3-1.2.2/PyWebWinUI3.egg-info → pywebwinui3-1.2.4}/PKG-INFO +1 -1
  2. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4/PyWebWinUI3.egg-info}/PKG-INFO +1 -1
  3. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/__init__.py +1 -1
  4. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/core.py +199 -61
  5. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/event.py +3 -1
  6. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/LICENSE +0 -0
  7. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/MANIFEST.in +0 -0
  8. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/NOTICE +0 -0
  9. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/PyWebWinUI3.egg-info/SOURCES.txt +0 -0
  10. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/PyWebWinUI3.egg-info/dependency_links.txt +0 -0
  11. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/PyWebWinUI3.egg-info/requires.txt +0 -0
  12. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/PyWebWinUI3.egg-info/top_level.txt +0 -0
  13. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/README.md +0 -0
  14. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pyproject.toml +0 -0
  15. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/type.py +0 -0
  16. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/util.py +0 -0
  17. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/web/Pretendard/PretendardVariable.subset.0.woff2 +0 -0
  18. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/web/Pretendard/PretendardVariable.subset.1.woff2 +0 -0
  19. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/web/Pretendard/PretendardVariable.subset.10.woff2 +0 -0
  20. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/web/Pretendard/PretendardVariable.subset.11.woff2 +0 -0
  21. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/web/Pretendard/PretendardVariable.subset.12.woff2 +0 -0
  22. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/web/Pretendard/PretendardVariable.subset.13.woff2 +0 -0
  23. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/web/Pretendard/PretendardVariable.subset.14.woff2 +0 -0
  24. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/web/Pretendard/PretendardVariable.subset.15.woff2 +0 -0
  25. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/web/Pretendard/PretendardVariable.subset.16.woff2 +0 -0
  26. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/web/Pretendard/PretendardVariable.subset.17.woff2 +0 -0
  27. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/web/Pretendard/PretendardVariable.subset.18.woff2 +0 -0
  28. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/web/Pretendard/PretendardVariable.subset.19.woff2 +0 -0
  29. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/web/Pretendard/PretendardVariable.subset.2.woff2 +0 -0
  30. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/web/Pretendard/PretendardVariable.subset.20.woff2 +0 -0
  31. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/web/Pretendard/PretendardVariable.subset.21.woff2 +0 -0
  32. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/web/Pretendard/PretendardVariable.subset.22.woff2 +0 -0
  33. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/web/Pretendard/PretendardVariable.subset.23.woff2 +0 -0
  34. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/web/Pretendard/PretendardVariable.subset.24.woff2 +0 -0
  35. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/web/Pretendard/PretendardVariable.subset.25.woff2 +0 -0
  36. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/web/Pretendard/PretendardVariable.subset.26.woff2 +0 -0
  37. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/web/Pretendard/PretendardVariable.subset.27.woff2 +0 -0
  38. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/web/Pretendard/PretendardVariable.subset.28.woff2 +0 -0
  39. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/web/Pretendard/PretendardVariable.subset.29.woff2 +0 -0
  40. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/web/Pretendard/PretendardVariable.subset.3.woff2 +0 -0
  41. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/web/Pretendard/PretendardVariable.subset.30.woff2 +0 -0
  42. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/web/Pretendard/PretendardVariable.subset.31.woff2 +0 -0
  43. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/web/Pretendard/PretendardVariable.subset.32.woff2 +0 -0
  44. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/web/Pretendard/PretendardVariable.subset.33.woff2 +0 -0
  45. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/web/Pretendard/PretendardVariable.subset.34.woff2 +0 -0
  46. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/web/Pretendard/PretendardVariable.subset.35.woff2 +0 -0
  47. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/web/Pretendard/PretendardVariable.subset.36.woff2 +0 -0
  48. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/web/Pretendard/PretendardVariable.subset.37.woff2 +0 -0
  49. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/web/Pretendard/PretendardVariable.subset.38.woff2 +0 -0
  50. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/web/Pretendard/PretendardVariable.subset.39.woff2 +0 -0
  51. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/web/Pretendard/PretendardVariable.subset.4.woff2 +0 -0
  52. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/web/Pretendard/PretendardVariable.subset.40.woff2 +0 -0
  53. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/web/Pretendard/PretendardVariable.subset.41.woff2 +0 -0
  54. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/web/Pretendard/PretendardVariable.subset.42.woff2 +0 -0
  55. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/web/Pretendard/PretendardVariable.subset.43.woff2 +0 -0
  56. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/web/Pretendard/PretendardVariable.subset.44.woff2 +0 -0
  57. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/web/Pretendard/PretendardVariable.subset.45.woff2 +0 -0
  58. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/web/Pretendard/PretendardVariable.subset.46.woff2 +0 -0
  59. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/web/Pretendard/PretendardVariable.subset.47.woff2 +0 -0
  60. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/web/Pretendard/PretendardVariable.subset.48.woff2 +0 -0
  61. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/web/Pretendard/PretendardVariable.subset.49.woff2 +0 -0
  62. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/web/Pretendard/PretendardVariable.subset.5.woff2 +0 -0
  63. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/web/Pretendard/PretendardVariable.subset.50.woff2 +0 -0
  64. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/web/Pretendard/PretendardVariable.subset.51.woff2 +0 -0
  65. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/web/Pretendard/PretendardVariable.subset.52.woff2 +0 -0
  66. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/web/Pretendard/PretendardVariable.subset.53.woff2 +0 -0
  67. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/web/Pretendard/PretendardVariable.subset.54.woff2 +0 -0
  68. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/web/Pretendard/PretendardVariable.subset.55.woff2 +0 -0
  69. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/web/Pretendard/PretendardVariable.subset.56.woff2 +0 -0
  70. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/web/Pretendard/PretendardVariable.subset.57.woff2 +0 -0
  71. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/web/Pretendard/PretendardVariable.subset.58.woff2 +0 -0
  72. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/web/Pretendard/PretendardVariable.subset.59.woff2 +0 -0
  73. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/web/Pretendard/PretendardVariable.subset.6.woff2 +0 -0
  74. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/web/Pretendard/PretendardVariable.subset.60.woff2 +0 -0
  75. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/web/Pretendard/PretendardVariable.subset.61.woff2 +0 -0
  76. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/web/Pretendard/PretendardVariable.subset.62.woff2 +0 -0
  77. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/web/Pretendard/PretendardVariable.subset.63.woff2 +0 -0
  78. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/web/Pretendard/PretendardVariable.subset.64.woff2 +0 -0
  79. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/web/Pretendard/PretendardVariable.subset.65.woff2 +0 -0
  80. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/web/Pretendard/PretendardVariable.subset.66.woff2 +0 -0
  81. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/web/Pretendard/PretendardVariable.subset.67.woff2 +0 -0
  82. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/web/Pretendard/PretendardVariable.subset.68.woff2 +0 -0
  83. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/web/Pretendard/PretendardVariable.subset.69.woff2 +0 -0
  84. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/web/Pretendard/PretendardVariable.subset.7.woff2 +0 -0
  85. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/web/Pretendard/PretendardVariable.subset.70.woff2 +0 -0
  86. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/web/Pretendard/PretendardVariable.subset.71.woff2 +0 -0
  87. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/web/Pretendard/PretendardVariable.subset.72.woff2 +0 -0
  88. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/web/Pretendard/PretendardVariable.subset.73.woff2 +0 -0
  89. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/web/Pretendard/PretendardVariable.subset.74.woff2 +0 -0
  90. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/web/Pretendard/PretendardVariable.subset.75.woff2 +0 -0
  91. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/web/Pretendard/PretendardVariable.subset.76.woff2 +0 -0
  92. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/web/Pretendard/PretendardVariable.subset.77.woff2 +0 -0
  93. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/web/Pretendard/PretendardVariable.subset.78.woff2 +0 -0
  94. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/web/Pretendard/PretendardVariable.subset.79.woff2 +0 -0
  95. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/web/Pretendard/PretendardVariable.subset.8.woff2 +0 -0
  96. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/web/Pretendard/PretendardVariable.subset.80.woff2 +0 -0
  97. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/web/Pretendard/PretendardVariable.subset.81.woff2 +0 -0
  98. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/web/Pretendard/PretendardVariable.subset.82.woff2 +0 -0
  99. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/web/Pretendard/PretendardVariable.subset.83.woff2 +0 -0
  100. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/web/Pretendard/PretendardVariable.subset.84.woff2 +0 -0
  101. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/web/Pretendard/PretendardVariable.subset.85.woff2 +0 -0
  102. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/web/Pretendard/PretendardVariable.subset.86.woff2 +0 -0
  103. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/web/Pretendard/PretendardVariable.subset.87.woff2 +0 -0
  104. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/web/Pretendard/PretendardVariable.subset.88.woff2 +0 -0
  105. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/web/Pretendard/PretendardVariable.subset.89.woff2 +0 -0
  106. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/web/Pretendard/PretendardVariable.subset.9.woff2 +0 -0
  107. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/web/Pretendard/PretendardVariable.subset.90.woff2 +0 -0
  108. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/web/Pretendard/PretendardVariable.subset.91.woff2 +0 -0
  109. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/web/Pretendard/Variable-dynamic-subset.min.css +0 -0
  110. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/web/SegoeFluentIcons.ttf +0 -0
  111. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/web/_app/env.js +0 -0
  112. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/web/_app/immutable/assets/2.YxEoeVwz.css +0 -0
  113. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/web/_app/immutable/chunks/6pQH9Hkv.js +0 -0
  114. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/web/_app/immutable/chunks/B-XLOWlt.js +0 -0
  115. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/web/_app/immutable/chunks/CGGCsFu4.js +0 -0
  116. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/web/_app/immutable/chunks/CW0wlPPy.js +0 -0
  117. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/web/_app/immutable/chunks/CZPLFskb.js +0 -0
  118. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/web/_app/immutable/chunks/CZuXpvpo.js +0 -0
  119. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/web/_app/immutable/chunks/D94BNvJJ.js +0 -0
  120. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/web/_app/immutable/chunks/DF1x2LYX.js +0 -0
  121. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/web/_app/immutable/entry/app.B-Q6XOuJ.js +0 -0
  122. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/web/_app/immutable/entry/start.C1-i6FUr.js +0 -0
  123. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/web/_app/immutable/nodes/0.C49PHrK2.js +0 -0
  124. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/web/_app/immutable/nodes/1.a96iIGzo.js +0 -0
  125. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/web/_app/immutable/nodes/2.Ofs4dh3G.js +0 -0
  126. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/web/_app/version.json +0 -0
  127. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/pywebwinui3/web/index.html +0 -0
  128. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/requirements.txt +0 -0
  129. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/setup.cfg +0 -0
  130. {pywebwinui3-1.2.2 → pywebwinui3-1.2.4}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: PyWebWinUI3
3
- Version: 1.2.2
3
+ Version: 1.2.4
4
4
  Summary: Create modern WinUI3-style desktop UIs in Python using pywebview and a Svelte frontend.
5
5
  Home-page: https://github.com/Haruna5718/PyWebWinUI3
6
6
  Author: Haruna5718
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: PyWebWinUI3
3
- Version: 1.2.2
3
+ Version: 1.2.4
4
4
  Summary: Create modern WinUI3-style desktop UIs in Python using pywebview and a Svelte frontend.
5
5
  Home-page: https://github.com/Haruna5718/PyWebWinUI3
6
6
  Author: Haruna5718
@@ -1,3 +1,3 @@
1
1
  __all__ = ["core", "event", "util", "type"]
2
2
 
3
- __version__ = '1.2.2'
3
+ __version__ = '1.2.4'
@@ -16,7 +16,7 @@ from urllib.parse import unquote, urlparse, urlunparse
16
16
  from ctypes import wintypes
17
17
 
18
18
  import webview
19
- from hPyT import title_bar
19
+ from hPyT import title_bar, window_dwm
20
20
 
21
21
  from .event import Event, PathEvent
22
22
  from .type import Status
@@ -193,6 +193,7 @@ class _JsApi:
193
193
  class WindowEvents:
194
194
  def __init__(self) -> None:
195
195
  self.windowReady = Event()
196
+ self.closing = Event()
196
197
  self.closed = Event()
197
198
  self.accentColorChange = Event()
198
199
  self.valueChange = PathEvent()
@@ -211,8 +212,12 @@ class MainWindow:
211
212
  self._setup_fired = False
212
213
  self._minimum_width = DEFAULT_WINDOW_MIN_WIDTH
213
214
  self._minimum_height = DEFAULT_WINDOW_MIN_HEIGHT
215
+ self._defer_window_chrome = False
216
+ self._startup_cloaked = False
214
217
  self._sync_lock = threading.Lock()
215
218
  self._pending_sync: dict[str, object] = {}
219
+ self._sync_event = threading.Event()
220
+ self._sync_thread: threading.Thread | None = None
216
221
  self._ui_server: _UiHttpServer | None = None
217
222
  self._ui_server_thread: threading.Thread | None = None
218
223
  self._ui_origin = ""
@@ -242,7 +247,7 @@ class MainWindow:
242
247
  _apply_menu_theme_support(self.values.get("system_theme"))
243
248
 
244
249
  self._window = webview.create_window(
245
- self._current_title(),
250
+ self.values.get("system_title", self._title),
246
251
  f"{self._ui_origin}/index.html",
247
252
  js_api=self.api,
248
253
  background_color="#202020",
@@ -252,16 +257,18 @@ class MainWindow:
252
257
  min_size=(self._minimum_width, self._minimum_height),
253
258
  on_top=bool(self.values.get("system_pin", False)),
254
259
  )
255
- self.show = self._window.show
256
- self.restore = self._window.restore
257
- self.hide = self._window.hide
258
- self.destroy = self._window.destroy
259
- self.minimize = self._window.minimize
260
+ self.show = self._show_window
261
+ self.restore = self._restore_window
262
+ self.hide = self._hide_window
263
+ self.destroy = self._destroy_window
264
+ self.minimize = self._minimize_window
260
265
  self.api._init(self)
261
266
  self._window.events.before_show += self._before_show
267
+ self._window.events.closing += self._on_closing
262
268
  self._window.events.closed += self._on_closed
263
- self._window.events.maximized += lambda *_: self._set_window_maximized_state(True)
264
- self._window.events.restored += lambda *_: self._set_window_maximized_state(False)
269
+ self._window.events.maximized += self._on_window_maximized_state
270
+ self._window.events.restored += self._on_window_restored_state
271
+ self._window.events.restored += self._on_window_restored
265
272
 
266
273
  core_logger.debug("Window created")
267
274
 
@@ -288,6 +295,9 @@ class MainWindow:
288
295
  def onSetup(self):
289
296
  return self._event_decorator(self.events.windowReady)
290
297
 
298
+ def onClosing(self):
299
+ return self._event_decorator(self.events.closing)
300
+
291
301
  def onExit(self):
292
302
  return self._event_decorator(self.events.closed)
293
303
 
@@ -317,11 +327,11 @@ class MainWindow:
317
327
  def addPage(self, pageFile: str | Path | None = None, pageData: dict | None = None):
318
328
  if pageFile and not pageData:
319
329
  pageData = loadPage(pageFile)
320
- logger.debug("Page added: %s", pageData["attr"]["path"])
321
- self.values["system_pages"] = {
322
- **(self.values["system_pages"] or {}),
323
- pageData["attr"]["path"]: pageData,
324
- }
330
+ page_path = str(pageData["attr"]["path"])
331
+ logger.debug("Page added: %s", page_path)
332
+ if self.values["system_pages"] is None:
333
+ self.values["system_pages"] = {}
334
+ self.values.set(f"system_pages[{json.dumps(page_path, ensure_ascii=False)}]", pageData)
325
335
 
326
336
  def resolve_path(self, value: str | Path | None) -> Path | None:
327
337
  if value is None:
@@ -341,9 +351,6 @@ class MainWindow:
341
351
 
342
352
  return root_candidate.resolve()
343
353
 
344
- def _current_title(self):
345
- return self.values.get("system_title", self._title)
346
-
347
354
  def _window_handle(self) -> int | None:
348
355
  try:
349
356
  native = getattr(self._window, "native", None)
@@ -437,24 +444,151 @@ class MainWindow:
437
444
  try:
438
445
  hwnd = self._window.native.Handle.ToInt64()
439
446
  _apply_menu_theme_support(self.values.get("system_theme"), hwnd)
440
- title_bar.hide(hwnd)
441
- self._set_window_maximized_state(bool(_user32.IsZoomed(hwnd)), sync=False)
447
+ if self._defer_window_chrome:
448
+ window_dwm.toggle_cloak(hwnd, True)
449
+ self._startup_cloaked = True
450
+ else:
451
+ title_bar.hide(hwnd)
452
+ self._set_window_maximized_state(bool(_user32.IsZoomed(hwnd)), sync=False)
442
453
  except Exception:
443
454
  core_logger.debug("Failed to hide title bar", exc_info=True)
444
455
 
456
+ def _invoke_native(self, native, callback):
457
+ action_type = getattr(importlib.import_module("System"), "Action")
458
+ if native.InvokeRequired:
459
+ native.BeginInvoke(action_type(callback))
460
+ else:
461
+ callback()
462
+
463
+ def _invoke_native_sync(self, native, callback):
464
+ action_type = getattr(importlib.import_module("System"), "Action")
465
+ if native.InvokeRequired:
466
+ native.Invoke(action_type(callback))
467
+ else:
468
+ callback()
469
+
470
+ def _invoke_native_later(self, native, callback, delay: float):
471
+ timer = threading.Timer(delay, lambda: self._invoke_native(native, callback))
472
+ timer.daemon = True
473
+ timer.start()
474
+
475
+ def _on_window_maximized_state(self, *_):
476
+ self._set_window_maximized_state(True)
477
+
478
+ def _on_window_restored_state(self, *_):
479
+ self._set_window_maximized_state(False)
480
+
481
+ def _on_window_restored(self):
482
+ self._ensure_window_chrome()
483
+ self._refresh_client_layout()
484
+
485
+ def _ensure_window_chrome(self, delay: float = 0.08):
486
+ if not self._defer_window_chrome:
487
+ return
488
+
489
+ self._defer_window_chrome = False
490
+ native = getattr(self._window, "native", None)
491
+ if native is None:
492
+ return
493
+
494
+ def _apply():
495
+ try:
496
+ hwnd = int(native.Handle.ToInt64())
497
+ _apply_menu_theme_support(self.values.get("system_theme"), hwnd)
498
+ if self._startup_cloaked:
499
+ window_dwm.toggle_cloak(hwnd, False)
500
+ self._startup_cloaked = False
501
+ try:
502
+ title_bar.unhide(hwnd)
503
+ except Exception:
504
+ pass
505
+ title_bar.hide(hwnd)
506
+ self._set_window_maximized_state(bool(_user32.IsZoomed(hwnd)), sync=False)
507
+ except Exception:
508
+ core_logger.debug("Failed to ensure window chrome", exc_info=True)
509
+
510
+ self._invoke_native_later(native, _apply, delay)
511
+
512
+ def _refresh_client_layout(self, delay: float = 0.08):
513
+ native = getattr(self._window, "native", None)
514
+ if native is None:
515
+ return
516
+
517
+ forms = importlib.import_module("System.Windows.Forms")
518
+
519
+ def _apply():
520
+ try:
521
+ native.SuspendLayout()
522
+ webview_control = getattr(native, "webview", None)
523
+ if webview_control is not None:
524
+ webview_control.Dock = forms.DockStyle.Fill
525
+ webview_control.Bounds = native.ClientRectangle
526
+ webview_control.BringToFront()
527
+ webview_control.Invalidate()
528
+ webview_control.Update()
529
+ native.PerformLayout()
530
+ native.Invalidate(True)
531
+ native.Refresh()
532
+ except Exception:
533
+ core_logger.debug("Failed to refresh client layout", exc_info=True)
534
+ finally:
535
+ try:
536
+ native.ResumeLayout(True)
537
+ except Exception:
538
+ pass
539
+
540
+ self._invoke_native_later(native, _apply, delay)
541
+
542
+ def _show_window(self):
543
+ native = getattr(self._window, "native", None)
544
+ if native is None:
545
+ self._window.show()
546
+ else:
547
+ self._invoke_native_sync(native, self._window.show)
548
+ self._ensure_window_chrome()
549
+ self._refresh_client_layout()
550
+
551
+ def _restore_window(self):
552
+ native = getattr(self._window, "native", None)
553
+ if native is None:
554
+ self._window.restore()
555
+ else:
556
+ self._invoke_native_sync(native, self._window.restore)
557
+ self._ensure_window_chrome()
558
+ self._refresh_client_layout()
559
+
560
+ def _hide_window(self):
561
+ native = getattr(self._window, "native", None)
562
+ if native is None:
563
+ self._window.hide()
564
+ return
565
+ self._invoke_native_sync(native, self._window.hide)
566
+
567
+ def _destroy_window(self):
568
+ native = getattr(self._window, "native", None)
569
+ if native is None:
570
+ self._window.destroy()
571
+ return
572
+ self._invoke_native_sync(native, self._window.destroy)
573
+
574
+ def _minimize_window(self):
575
+ native = getattr(self._window, "native", None)
576
+ if native is None:
577
+ self._window.minimize()
578
+ return
579
+ self._invoke_native_sync(native, self._window.minimize)
580
+
581
+ def _on_closing(self, *_):
582
+ return not self.events.closing.set()
583
+
445
584
  def _on_closed(self):
446
585
  self.accent.stop()
586
+ with self._sync_lock:
587
+ self._pending_sync.clear()
588
+ self._sync_event.set()
447
589
  self._stop_ui_server()
448
590
  self.events.closed.set()
449
591
 
450
- def _dispatch_or_defer_sync(self, key: str, value):
451
- with self._sync_lock:
452
- if not self._frontend_ready:
453
- self._pending_sync[key] = value
454
- return
455
-
456
- self._dispatch_sync_value(key, value)
457
-
458
592
  def _dispatch_sync_value(self, key: str, value):
459
593
  if key == "system_title":
460
594
  try:
@@ -464,14 +598,39 @@ class MainWindow:
464
598
 
465
599
  script = f"window.syncValue({json.dumps(key, ensure_ascii=False)}, {json.dumps(value, ensure_ascii=False)}, false)"
466
600
  try:
467
- self._window.evaluate_js(script)
601
+ self._window.run_js(script)
468
602
  except Exception:
469
- with self._sync_lock:
470
- self._pending_sync[key] = value
471
603
  core_logger.debug("Failed to sync value %s", key, exc_info=True)
472
604
 
473
605
  def queue_sync_value(self, key: str, value):
474
- self._dispatch_or_defer_sync(key, value)
606
+ with self._sync_lock:
607
+ self._pending_sync[key] = value
608
+ frontend_ready = self._frontend_ready
609
+
610
+ if not frontend_ready:
611
+ return
612
+ self._ensure_sync_worker()
613
+ self._sync_event.set()
614
+
615
+ def _ensure_sync_worker(self):
616
+ if self._sync_thread and self._sync_thread.is_alive():
617
+ return
618
+ self._sync_thread = threading.Thread(target=self._sync_loop, daemon=True, name="PyWebWinUI3-Sync")
619
+ self._sync_thread.start()
620
+
621
+ def _sync_loop(self):
622
+ while True:
623
+ self._sync_event.wait()
624
+ while True:
625
+ with self._sync_lock:
626
+ if not self._pending_sync:
627
+ self._sync_event.clear()
628
+ break
629
+ pending = tuple(self._pending_sync.items())
630
+ self._pending_sync.clear()
631
+
632
+ for key, value in pending:
633
+ self._dispatch_sync_value(key, value)
475
634
 
476
635
  def _set_window_maximized_state(self, value: bool, *, sync: bool = True):
477
636
  value = bool(value)
@@ -499,12 +658,8 @@ class MainWindow:
499
658
 
500
659
  self._frontend_ready = True
501
660
 
502
- with self._sync_lock:
503
- pending_sync = tuple(self._pending_sync.items())
504
- self._pending_sync.clear()
505
-
506
- for key, value in pending_sync:
507
- self._dispatch_sync_value(key, value)
661
+ self._ensure_sync_worker()
662
+ self._sync_event.set()
508
663
 
509
664
  if not self._setup_fired:
510
665
  self._setup_fired = True
@@ -518,15 +673,10 @@ class MainWindow:
518
673
  self._window.on_top = state
519
674
  return
520
675
 
521
- action_type = getattr(importlib.import_module("System"), "Action")
522
-
523
676
  def _apply():
524
677
  self._window.on_top = state
525
678
 
526
- if native.InvokeRequired:
527
- native.BeginInvoke(action_type(_apply))
528
- else:
529
- _apply()
679
+ self._invoke_native(native, _apply)
530
680
  except Exception:
531
681
  core_logger.debug("Failed to set window on top", exc_info=True)
532
682
 
@@ -536,17 +686,12 @@ class MainWindow:
536
686
  if native is None:
537
687
  return
538
688
 
539
- action_type = getattr(importlib.import_module("System"), "Action")
540
-
541
689
  def _apply():
542
690
  hwnd = int(native.Handle.ToInt64())
543
691
  _user32.ReleaseCapture()
544
692
  _user32.SendMessageW(hwnd, 0x00A1, 2, 0) # WM_NCLBUTTONDOWN, HTCAPTION
545
693
 
546
- if native.InvokeRequired:
547
- native.BeginInvoke(action_type(_apply))
548
- else:
549
- _apply()
694
+ self._invoke_native(native, _apply)
550
695
  except Exception:
551
696
  core_logger.debug("Failed to start system window drag", exc_info=True)
552
697
 
@@ -556,18 +701,13 @@ class MainWindow:
556
701
  if native is None:
557
702
  return
558
703
 
559
- action_type = getattr(importlib.import_module("System"), "Action")
560
-
561
704
  def _apply():
562
705
  hwnd = int(native.Handle.ToInt64())
563
706
  is_zoomed = bool(_user32.IsZoomed(hwnd))
564
707
  command = 9 if is_zoomed else 3 # SW_RESTORE / SW_MAXIMIZE
565
708
  _user32.ShowWindow(hwnd, command)
566
709
 
567
- if native.InvokeRequired:
568
- native.BeginInvoke(action_type(_apply))
569
- else:
570
- _apply()
710
+ self._invoke_native(native, _apply)
571
711
  except Exception:
572
712
  core_logger.debug("Failed to toggle window maximize", exc_info=True)
573
713
 
@@ -577,8 +717,6 @@ class MainWindow:
577
717
  if native is None:
578
718
  return
579
719
 
580
- action_type = getattr(importlib.import_module("System"), "Action")
581
-
582
720
  def _apply():
583
721
  hwnd = int(native.Handle.ToInt64())
584
722
  menu = _user32.GetSystemMenu(hwnd, False)
@@ -604,10 +742,7 @@ class MainWindow:
604
742
  _user32.PostMessageW(hwnd, 0x0112, command, 0) # WM_SYSCOMMAND
605
743
  _user32.PostMessageW(hwnd, 0x0000, 0, 0) # WM_NULL
606
744
 
607
- if native.InvokeRequired:
608
- native.BeginInvoke(action_type(_apply))
609
- else:
610
- _apply()
745
+ self._invoke_native(native, _apply)
611
746
  except Exception:
612
747
  core_logger.debug("Failed to show window system menu", exc_info=True)
613
748
 
@@ -663,6 +798,7 @@ class MainWindow:
663
798
  debug: bool = False,
664
799
  *,
665
800
  hidden: bool = False,
801
+ minimized: bool = False,
666
802
  on_top: bool | None = None,
667
803
  width: int | None = None,
668
804
  height: int | None = None,
@@ -673,7 +809,9 @@ class MainWindow:
673
809
  self._minimum_width = max(1, int(min_width))
674
810
  self._minimum_height = max(1, int(min_height))
675
811
  self._window.min_size = (self._minimum_width, self._minimum_height)
812
+ self._defer_window_chrome = bool(hidden or minimized)
676
813
  self._window.hidden = bool(hidden)
814
+ self._window.minimized = bool(minimized and not hidden)
677
815
 
678
816
  if width is not None and height is not None:
679
817
  width = max(self._minimum_width, int(width))
@@ -12,11 +12,13 @@ class Event:
12
12
  self.items: list[Callable[..., Any]] = []
13
13
 
14
14
  def set(self, *args: Any):
15
+ result = False
15
16
  for func in tuple(self.items):
16
17
  try:
17
- func(*args)
18
+ result = bool(func(*args)) or result
18
19
  except Exception:
19
20
  logger.exception("Event callback failed")
21
+ return result
20
22
 
21
23
  def _add(self, item: Callable[..., Any]):
22
24
  self.items.append(item)
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes