akanjs 3.0.0-beta.20 → 3.0.0-beta.21

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 (731) hide show
  1. package/README.ko.md +0 -1
  2. package/README.md +0 -1
  3. package/base/baseEnv.ts +40 -3
  4. package/client/cookie.ts +56 -20
  5. package/client/device.ts +47 -95
  6. package/client/frameConfig.ts +2 -2
  7. package/client/native.ts +44 -0
  8. package/client/router.ts +11 -1
  9. package/client/rscNavigation.ts +5 -0
  10. package/client/storage.ts +68 -39
  11. package/fetch/client/fetchClient.ts +13 -4
  12. package/index.ts +47 -46
  13. package/package.json +6 -87
  14. package/server/devtools/signalSerializer.ts +1 -2
  15. package/server/hmr/devHmrController.ts +29 -11
  16. package/server/resolver/signal.resolver.ts +1 -10
  17. package/server/routeTreeBuilder.ts +8 -11
  18. package/server/routing/apiRouter.ts +15 -2
  19. package/server/rscClient.tsx +1 -2
  20. package/server/ssrFromRscRenderer.tsx +2 -0
  21. package/server/webRouter.ts +1 -0
  22. package/signal/CrossSiteGuard.ts +34 -2
  23. package/signal/endpoint.ts +12 -7
  24. package/signal/endpointInfo.ts +13 -0
  25. package/signal/internal.ts +9 -5
  26. package/signal/serializer/fetch.serializer.ts +6 -3
  27. package/signal/slice.ts +34 -24
  28. package/store/baseSt.ts +0 -1
  29. package/store/storeInstance.ts +29 -17
  30. package/types/client/cookie.d.ts +6 -4
  31. package/types/client/device.d.ts +7 -10
  32. package/types/client/native.d.ts +26 -0
  33. package/types/client/rscNavigation.d.ts +4 -0
  34. package/types/client/storage.d.ts +8 -1
  35. package/types/index.d.ts +48 -44
  36. package/types/server/hmr/devHmrController.d.ts +2 -1
  37. package/types/server/resolver/signal.resolver.d.ts +0 -1
  38. package/types/server/rscClient.d.ts +0 -3
  39. package/types/signal/CrossSiteGuard.d.ts +7 -2
  40. package/types/signal/endpoint.d.ts +1 -1
  41. package/types/signal/endpointInfo.d.ts +3 -0
  42. package/types/signal/slice.d.ts +3 -2
  43. package/types/store/baseSt.d.ts +0 -13
  44. package/types/vendor/@akanjs/native/packages/cli/src/api.d.ts +182 -0
  45. package/types/vendor/@akanjs/native/packages/cli/src/commands/build.d.ts +28 -0
  46. package/types/vendor/@akanjs/native/packages/cli/src/commands/compat.d.ts +2 -0
  47. package/types/vendor/@akanjs/native/packages/cli/src/commands/dev.d.ts +2 -0
  48. package/types/vendor/@akanjs/native/packages/cli/src/commands/doctor.d.ts +37 -0
  49. package/types/vendor/@akanjs/native/packages/cli/src/commands/plugin.d.ts +2 -0
  50. package/types/vendor/@akanjs/native/packages/cli/src/commands/signing.d.ts +2 -0
  51. package/types/vendor/@akanjs/native/packages/cli/src/commands/test.d.ts +2 -0
  52. package/types/vendor/@akanjs/native/packages/cli/src/commands/toolchain.d.ts +2 -0
  53. package/types/vendor/@akanjs/native/packages/cli/src/commands/update.d.ts +2 -0
  54. package/types/vendor/@akanjs/native/packages/cli/src/config.d.ts +278 -0
  55. package/types/vendor/@akanjs/native/packages/cli/src/index.d.ts +2 -0
  56. package/types/vendor/@akanjs/native/packages/cli/src/lib/acl.d.ts +21 -0
  57. package/types/vendor/@akanjs/native/packages/cli/src/lib/apilevel.d.ts +40 -0
  58. package/types/vendor/@akanjs/native/packages/cli/src/lib/apk.d.ts +36 -0
  59. package/types/vendor/@akanjs/native/packages/cli/src/lib/args.d.ts +9 -0
  60. package/types/vendor/@akanjs/native/packages/cli/src/lib/boot.d.ts +32 -0
  61. package/types/vendor/@akanjs/native/packages/cli/src/lib/chrome.d.ts +6 -0
  62. package/types/vendor/@akanjs/native/packages/cli/src/lib/codegen.d.ts +94 -0
  63. package/types/vendor/@akanjs/native/packages/cli/src/lib/compat.d.ts +49 -0
  64. package/types/vendor/@akanjs/native/packages/cli/src/lib/configkeys.d.ts +2 -0
  65. package/types/vendor/@akanjs/native/packages/cli/src/lib/csp.d.ts +51 -0
  66. package/types/vendor/@akanjs/native/packages/cli/src/lib/env.d.ts +44 -0
  67. package/types/vendor/@akanjs/native/packages/cli/src/lib/exec.d.ts +31 -0
  68. package/types/vendor/@akanjs/native/packages/cli/src/lib/googleservices.d.ts +2 -0
  69. package/types/vendor/@akanjs/native/packages/cli/src/lib/hmr.d.ts +120 -0
  70. package/types/vendor/@akanjs/native/packages/cli/src/lib/html.d.ts +20 -0
  71. package/types/vendor/@akanjs/native/packages/cli/src/lib/icons.d.ts +44 -0
  72. package/types/vendor/@akanjs/native/packages/cli/src/lib/image.d.ts +21 -0
  73. package/types/vendor/@akanjs/native/packages/cli/src/lib/iossigning.d.ts +81 -0
  74. package/types/vendor/@akanjs/native/packages/cli/src/lib/launch.d.ts +51 -0
  75. package/types/vendor/@akanjs/native/packages/cli/src/lib/log.d.ts +42 -0
  76. package/types/vendor/@akanjs/native/packages/cli/src/lib/manifestmerge.d.ts +18 -0
  77. package/types/vendor/@akanjs/native/packages/cli/src/lib/maven.d.ts +97 -0
  78. package/types/vendor/@akanjs/native/packages/cli/src/lib/names.d.ts +45 -0
  79. package/types/vendor/@akanjs/native/packages/cli/src/lib/native-plugins.d.ts +67 -0
  80. package/types/vendor/@akanjs/native/packages/cli/src/lib/nativeconfig.d.ts +11 -0
  81. package/types/vendor/@akanjs/native/packages/cli/src/lib/permissions.d.ts +10 -0
  82. package/types/vendor/@akanjs/native/packages/cli/src/lib/plist.d.ts +11 -0
  83. package/types/vendor/@akanjs/native/packages/cli/src/lib/png.d.ts +11 -0
  84. package/types/vendor/@akanjs/native/packages/cli/src/lib/prepare.d.ts +138 -0
  85. package/types/vendor/@akanjs/native/packages/cli/src/lib/privacy.d.ts +13 -0
  86. package/types/vendor/@akanjs/native/packages/cli/src/lib/project.d.ts +208 -0
  87. package/types/vendor/@akanjs/native/packages/cli/src/lib/root.d.ts +1 -0
  88. package/types/vendor/@akanjs/native/packages/cli/src/lib/routes.d.ts +1 -0
  89. package/types/vendor/@akanjs/native/packages/cli/src/lib/serve.d.ts +17 -0
  90. package/types/vendor/@akanjs/native/packages/cli/src/lib/signing.d.ts +14 -0
  91. package/types/vendor/@akanjs/native/packages/cli/src/lib/spec.d.ts +96 -0
  92. package/types/vendor/@akanjs/native/packages/cli/src/lib/toolchains.d.ts +150 -0
  93. package/types/vendor/@akanjs/native/packages/cli/src/lib/updates.d.ts +77 -0
  94. package/types/vendor/@akanjs/native/packages/cli/src/lib/vectors.d.ts +13 -0
  95. package/types/vendor/@akanjs/native/packages/cli/src/lib/xml.d.ts +13 -0
  96. package/types/vendor/@akanjs/native/packages/cli/src/platforms/android.d.ts +57 -0
  97. package/types/vendor/@akanjs/native/packages/cli/src/platforms/desktop-update.d.ts +4 -0
  98. package/types/vendor/@akanjs/native/packages/cli/src/platforms/desktop.d.ts +40 -0
  99. package/types/vendor/@akanjs/native/packages/cli/src/platforms/index.d.ts +14 -0
  100. package/types/vendor/@akanjs/native/packages/cli/src/platforms/ios.d.ts +44 -0
  101. package/types/vendor/@akanjs/native/packages/cli/src/platforms/linux.d.ts +6 -0
  102. package/types/vendor/@akanjs/native/packages/cli/src/platforms/macos.d.ts +7 -0
  103. package/types/vendor/@akanjs/native/packages/cli/src/platforms/targets.d.ts +4 -0
  104. package/types/vendor/@akanjs/native/packages/cli/src/platforms/web-run.d.ts +15 -0
  105. package/types/vendor/@akanjs/native/packages/cli/src/platforms/web.d.ts +2 -0
  106. package/types/vendor/@akanjs/native/packages/cli/src/platforms/windows.d.ts +8 -0
  107. package/types/vendor/@akanjs/native/packages/cli/src/platforms.d.ts +1 -0
  108. package/types/vendor/@akanjs/native/packages/cli/src.d.ts +1 -0
  109. package/types/vendor/@akanjs/native/packages/core/src/acl.d.ts +97 -0
  110. package/types/vendor/@akanjs/native/packages/core/src/boot.d.ts +66 -0
  111. package/types/vendor/@akanjs/native/packages/core/src/contract.d.ts +35 -0
  112. package/types/vendor/@akanjs/native/packages/core/src/errors.d.ts +27 -0
  113. package/types/vendor/@akanjs/native/packages/core/src/files.d.ts +23 -0
  114. package/types/vendor/@akanjs/native/packages/core/src/index.d.ts +14 -0
  115. package/types/vendor/@akanjs/native/packages/core/src/kernel.d.ts +112 -0
  116. package/types/vendor/@akanjs/native/packages/core/src/live.d.ts +12 -0
  117. package/types/vendor/@akanjs/native/packages/core/src/mime.d.ts +2 -0
  118. package/types/vendor/@akanjs/native/packages/core/src/plugin.d.ts +71 -0
  119. package/types/vendor/@akanjs/native/packages/core/src/protocol.d.ts +109 -0
  120. package/types/vendor/@akanjs/native/packages/core/src/runtime.d.ts +66 -0
  121. package/types/vendor/@akanjs/native/packages/core/src/state.d.ts +28 -0
  122. package/types/vendor/@akanjs/native/packages/core/src/testing.d.ts +41 -0
  123. package/types/vendor/@akanjs/native/packages/core/src/version.d.ts +2 -0
  124. package/types/vendor/@akanjs/native/packages/core/src/veto.d.ts +17 -0
  125. package/types/vendor/@akanjs/native/packages/core/src.d.ts +1 -0
  126. package/types/vendor/@akanjs/native/packages/desktop/src/deeplinks.d.ts +24 -0
  127. package/types/vendor/@akanjs/native/packages/desktop/src/delta.d.ts +2 -0
  128. package/types/vendor/@akanjs/native/packages/desktop/src/dispatcher.d.ts +95 -0
  129. package/types/vendor/@akanjs/native/packages/desktop/src/ffi.d.ts +144 -0
  130. package/types/vendor/@akanjs/native/packages/desktop/src/host.d.ts +11 -0
  131. package/types/vendor/@akanjs/native/packages/desktop/src/lifecycle.d.ts +40 -0
  132. package/types/vendor/@akanjs/native/packages/desktop/src/main.d.ts +4 -0
  133. package/types/vendor/@akanjs/native/packages/desktop/src/page-veto.d.ts +17 -0
  134. package/types/vendor/@akanjs/native/packages/desktop/src/paths.d.ts +25 -0
  135. package/types/vendor/@akanjs/native/packages/desktop/src/plugin.d.ts +179 -0
  136. package/types/vendor/@akanjs/native/packages/react/src/index.d.ts +8 -0
  137. package/types/vendor/@akanjs/native/packages/react/src.d.ts +1 -0
  138. package/types/vendor/@akanjs/native/plugins/accessibility/src/announce.d.ts +8 -0
  139. package/types/vendor/@akanjs/native/plugins/accessibility/src/index.d.ts +47 -0
  140. package/types/vendor/@akanjs/native/plugins/accessibility/src/web.d.ts +4 -0
  141. package/types/vendor/@akanjs/native/plugins/accessibility/src.d.ts +1 -0
  142. package/types/vendor/@akanjs/native/plugins/app/src/desktop.d.ts +3 -0
  143. package/types/vendor/@akanjs/native/plugins/app/src/index.d.ts +66 -0
  144. package/types/vendor/@akanjs/native/plugins/app/src/web.d.ts +2 -0
  145. package/types/vendor/@akanjs/native/plugins/app/src.d.ts +1 -0
  146. package/types/vendor/@akanjs/native/plugins/app-state/src/index.d.ts +19 -0
  147. package/types/vendor/@akanjs/native/plugins/app-state/src/web.d.ts +2 -0
  148. package/types/vendor/@akanjs/native/plugins/app-state/src.d.ts +1 -0
  149. package/types/vendor/@akanjs/native/plugins/appearance/src/desktop.d.ts +9 -0
  150. package/types/vendor/@akanjs/native/plugins/appearance/src/index.d.ts +32 -0
  151. package/types/vendor/@akanjs/native/plugins/appearance/src/setting.d.ts +6 -0
  152. package/types/vendor/@akanjs/native/plugins/appearance/src/web.d.ts +3 -0
  153. package/types/vendor/@akanjs/native/plugins/appearance/src.d.ts +1 -0
  154. package/types/vendor/@akanjs/native/plugins/auth-session/src/args.d.ts +18 -0
  155. package/types/vendor/@akanjs/native/plugins/auth-session/src/desktop.d.ts +17 -0
  156. package/types/vendor/@akanjs/native/plugins/auth-session/src/index.d.ts +41 -0
  157. package/types/vendor/@akanjs/native/plugins/auth-session/src.d.ts +1 -0
  158. package/types/vendor/@akanjs/native/plugins/autostart/src/desktop.d.ts +44 -0
  159. package/types/vendor/@akanjs/native/plugins/autostart/src/index.d.ts +44 -0
  160. package/types/vendor/@akanjs/native/plugins/autostart/src.d.ts +1 -0
  161. package/types/vendor/@akanjs/native/plugins/badge/src/count.d.ts +4 -0
  162. package/types/vendor/@akanjs/native/plugins/badge/src/desktop.d.ts +3 -0
  163. package/types/vendor/@akanjs/native/plugins/badge/src/index.d.ts +37 -0
  164. package/types/vendor/@akanjs/native/plugins/badge/src/web.d.ts +2 -0
  165. package/types/vendor/@akanjs/native/plugins/badge/src.d.ts +1 -0
  166. package/types/vendor/@akanjs/native/plugins/biometric/src/index.d.ts +53 -0
  167. package/types/vendor/@akanjs/native/plugins/biometric/src.d.ts +1 -0
  168. package/types/vendor/@akanjs/native/plugins/browser/src/args.d.ts +8 -0
  169. package/types/vendor/@akanjs/native/plugins/browser/src/desktop.d.ts +9 -0
  170. package/types/vendor/@akanjs/native/plugins/browser/src/index.d.ts +36 -0
  171. package/types/vendor/@akanjs/native/plugins/browser/src/web.d.ts +2 -0
  172. package/types/vendor/@akanjs/native/plugins/browser/src.d.ts +1 -0
  173. package/types/vendor/@akanjs/native/plugins/camera/src/desktop.d.ts +5 -0
  174. package/types/vendor/@akanjs/native/plugins/camera/src/index.d.ts +55 -0
  175. package/types/vendor/@akanjs/native/plugins/camera/src/web.d.ts +2 -0
  176. package/types/vendor/@akanjs/native/plugins/camera/src.d.ts +1 -0
  177. package/types/vendor/@akanjs/native/plugins/clipboard/src/desktop.d.ts +8 -0
  178. package/types/vendor/@akanjs/native/plugins/clipboard/src/index.d.ts +40 -0
  179. package/types/vendor/@akanjs/native/plugins/clipboard/src/web.d.ts +2 -0
  180. package/types/vendor/@akanjs/native/plugins/clipboard/src.d.ts +1 -0
  181. package/types/vendor/@akanjs/native/plugins/device/src/desktop.d.ts +33 -0
  182. package/types/vendor/@akanjs/native/plugins/device/src/index.d.ts +55 -0
  183. package/types/vendor/@akanjs/native/plugins/device/src/web.d.ts +22 -0
  184. package/types/vendor/@akanjs/native/plugins/device/src.d.ts +1 -0
  185. package/types/vendor/@akanjs/native/plugins/dialog/src/desktop.d.ts +3 -0
  186. package/types/vendor/@akanjs/native/plugins/dialog/src/index.d.ts +60 -0
  187. package/types/vendor/@akanjs/native/plugins/dialog/src/options.d.ts +29 -0
  188. package/types/vendor/@akanjs/native/plugins/dialog/src/web.d.ts +2 -0
  189. package/types/vendor/@akanjs/native/plugins/dialog/src.d.ts +1 -0
  190. package/types/vendor/@akanjs/native/plugins/dock/src/desktop.d.ts +3 -0
  191. package/types/vendor/@akanjs/native/plugins/dock/src/index.d.ts +46 -0
  192. package/types/vendor/@akanjs/native/plugins/dock/src.d.ts +1 -0
  193. package/types/vendor/@akanjs/native/plugins/file-picker/src/common.d.ts +33 -0
  194. package/types/vendor/@akanjs/native/plugins/file-picker/src/desktop.d.ts +9 -0
  195. package/types/vendor/@akanjs/native/plugins/file-picker/src/index.d.ts +84 -0
  196. package/types/vendor/@akanjs/native/plugins/file-picker/src/web.d.ts +6 -0
  197. package/types/vendor/@akanjs/native/plugins/file-picker/src.d.ts +1 -0
  198. package/types/vendor/@akanjs/native/plugins/filesystem/src/common.d.ts +49 -0
  199. package/types/vendor/@akanjs/native/plugins/filesystem/src/desktop.d.ts +8 -0
  200. package/types/vendor/@akanjs/native/plugins/filesystem/src/index.d.ts +123 -0
  201. package/types/vendor/@akanjs/native/plugins/filesystem/src/web.d.ts +2 -0
  202. package/types/vendor/@akanjs/native/plugins/filesystem/src.d.ts +1 -0
  203. package/types/vendor/@akanjs/native/plugins/geolocation/src/index.d.ts +93 -0
  204. package/types/vendor/@akanjs/native/plugins/geolocation/src/web.d.ts +11 -0
  205. package/types/vendor/@akanjs/native/plugins/geolocation/src.d.ts +1 -0
  206. package/types/vendor/@akanjs/native/plugins/global-shortcut/src/desktop.d.ts +3 -0
  207. package/types/vendor/@akanjs/native/plugins/global-shortcut/src/index.d.ts +52 -0
  208. package/types/vendor/@akanjs/native/plugins/global-shortcut/src.d.ts +1 -0
  209. package/types/vendor/@akanjs/native/plugins/haptics/src/index.d.ts +31 -0
  210. package/types/vendor/@akanjs/native/plugins/haptics/src/web.d.ts +2 -0
  211. package/types/vendor/@akanjs/native/plugins/haptics/src.d.ts +1 -0
  212. package/types/vendor/@akanjs/native/plugins/http/src/common.d.ts +71 -0
  213. package/types/vendor/@akanjs/native/plugins/http/src/desktop.d.ts +5 -0
  214. package/types/vendor/@akanjs/native/plugins/http/src/index.d.ts +104 -0
  215. package/types/vendor/@akanjs/native/plugins/http/src/web.d.ts +2 -0
  216. package/types/vendor/@akanjs/native/plugins/http/src.d.ts +1 -0
  217. package/types/vendor/@akanjs/native/plugins/iap/src/index.d.ts +171 -0
  218. package/types/vendor/@akanjs/native/plugins/iap/src.d.ts +1 -0
  219. package/types/vendor/@akanjs/native/plugins/keep-awake/src/desktop.d.ts +15 -0
  220. package/types/vendor/@akanjs/native/plugins/keep-awake/src/index.d.ts +33 -0
  221. package/types/vendor/@akanjs/native/plugins/keep-awake/src/web.d.ts +2 -0
  222. package/types/vendor/@akanjs/native/plugins/keep-awake/src.d.ts +1 -0
  223. package/types/vendor/@akanjs/native/plugins/keyboard/src/index.d.ts +42 -0
  224. package/types/vendor/@akanjs/native/plugins/keyboard/src/web.d.ts +2 -0
  225. package/types/vendor/@akanjs/native/plugins/keyboard/src.d.ts +1 -0
  226. package/types/vendor/@akanjs/native/plugins/local-notifications/src/desktop.d.ts +29 -0
  227. package/types/vendor/@akanjs/native/plugins/local-notifications/src/index.d.ts +126 -0
  228. package/types/vendor/@akanjs/native/plugins/local-notifications/src/schedule.d.ts +38 -0
  229. package/types/vendor/@akanjs/native/plugins/local-notifications/src/timers.d.ts +25 -0
  230. package/types/vendor/@akanjs/native/plugins/local-notifications/src/web.d.ts +4 -0
  231. package/types/vendor/@akanjs/native/plugins/local-notifications/src.d.ts +1 -0
  232. package/types/vendor/@akanjs/native/plugins/menu/src/desktop.d.ts +3 -0
  233. package/types/vendor/@akanjs/native/plugins/menu/src/index.d.ts +85 -0
  234. package/types/vendor/@akanjs/native/plugins/menu/src.d.ts +1 -0
  235. package/types/vendor/@akanjs/native/plugins/network/src/index.d.ts +22 -0
  236. package/types/vendor/@akanjs/native/plugins/network/src/web.d.ts +3 -0
  237. package/types/vendor/@akanjs/native/plugins/network/src.d.ts +1 -0
  238. package/types/vendor/@akanjs/native/plugins/opener/src/desktop.d.ts +14 -0
  239. package/types/vendor/@akanjs/native/plugins/opener/src/index.d.ts +33 -0
  240. package/types/vendor/@akanjs/native/plugins/opener/src/url.d.ts +16 -0
  241. package/types/vendor/@akanjs/native/plugins/opener/src/web.d.ts +2 -0
  242. package/types/vendor/@akanjs/native/plugins/opener/src.d.ts +1 -0
  243. package/types/vendor/@akanjs/native/plugins/preferences/src/desktop.d.ts +3 -0
  244. package/types/vendor/@akanjs/native/plugins/preferences/src/index.d.ts +26 -0
  245. package/types/vendor/@akanjs/native/plugins/preferences/src/web.d.ts +2 -0
  246. package/types/vendor/@akanjs/native/plugins/preferences/src.d.ts +1 -0
  247. package/types/vendor/@akanjs/native/plugins/push/src/index.d.ts +57 -0
  248. package/types/vendor/@akanjs/native/plugins/push/src.d.ts +1 -0
  249. package/types/vendor/@akanjs/native/plugins/screen/src/desktop.d.ts +3 -0
  250. package/types/vendor/@akanjs/native/plugins/screen/src/index.d.ts +70 -0
  251. package/types/vendor/@akanjs/native/plugins/screen/src/web.d.ts +18 -0
  252. package/types/vendor/@akanjs/native/plugins/screen/src.d.ts +1 -0
  253. package/types/vendor/@akanjs/native/plugins/screen-orientation/src/index.d.ts +32 -0
  254. package/types/vendor/@akanjs/native/plugins/screen-orientation/src/types.d.ts +8 -0
  255. package/types/vendor/@akanjs/native/plugins/screen-orientation/src/web.d.ts +3 -0
  256. package/types/vendor/@akanjs/native/plugins/screen-orientation/src.d.ts +1 -0
  257. package/types/vendor/@akanjs/native/plugins/secure-storage/src/desktop.d.ts +16 -0
  258. package/types/vendor/@akanjs/native/plugins/secure-storage/src/index.d.ts +39 -0
  259. package/types/vendor/@akanjs/native/plugins/secure-storage/src.d.ts +1 -0
  260. package/types/vendor/@akanjs/native/plugins/share/src/index.d.ts +55 -0
  261. package/types/vendor/@akanjs/native/plugins/share/src/options.d.ts +6 -0
  262. package/types/vendor/@akanjs/native/plugins/share/src/web.d.ts +5 -0
  263. package/types/vendor/@akanjs/native/plugins/share/src.d.ts +1 -0
  264. package/types/vendor/@akanjs/native/plugins/single-instance/src/desktop.d.ts +8 -0
  265. package/types/vendor/@akanjs/native/plugins/single-instance/src/index.d.ts +25 -0
  266. package/types/vendor/@akanjs/native/plugins/single-instance/src/socket.d.ts +46 -0
  267. package/types/vendor/@akanjs/native/plugins/single-instance/src.d.ts +1 -0
  268. package/types/vendor/@akanjs/native/plugins/splash-screen/src/index.d.ts +19 -0
  269. package/types/vendor/@akanjs/native/plugins/splash-screen/src/web.d.ts +4 -0
  270. package/types/vendor/@akanjs/native/plugins/splash-screen/src.d.ts +1 -0
  271. package/types/vendor/@akanjs/native/plugins/sqlite/src/common.d.ts +34 -0
  272. package/types/vendor/@akanjs/native/plugins/sqlite/src/desktop.d.ts +6 -0
  273. package/types/vendor/@akanjs/native/plugins/sqlite/src/index.d.ts +115 -0
  274. package/types/vendor/@akanjs/native/plugins/sqlite/src.d.ts +1 -0
  275. package/types/vendor/@akanjs/native/plugins/toast/src/index.d.ts +30 -0
  276. package/types/vendor/@akanjs/native/plugins/toast/src/queue.d.ts +23 -0
  277. package/types/vendor/@akanjs/native/plugins/toast/src/web.d.ts +2 -0
  278. package/types/vendor/@akanjs/native/plugins/toast/src.d.ts +1 -0
  279. package/types/vendor/@akanjs/native/plugins/tray/src/desktop.d.ts +3 -0
  280. package/types/vendor/@akanjs/native/plugins/tray/src/index.d.ts +113 -0
  281. package/types/vendor/@akanjs/native/plugins/tray/src.d.ts +1 -0
  282. package/types/vendor/@akanjs/native/plugins/updates/src/desktop.d.ts +4 -0
  283. package/types/vendor/@akanjs/native/plugins/updates/src/index.d.ts +68 -0
  284. package/types/vendor/@akanjs/native/plugins/updates/src.d.ts +1 -0
  285. package/types/vendor/@akanjs/native/plugins/window/src/desktop.d.ts +6 -0
  286. package/types/vendor/@akanjs/native/plugins/window/src/index.d.ts +185 -0
  287. package/types/vendor/@akanjs/native/plugins/window/src/web.d.ts +2 -0
  288. package/types/vendor/@akanjs/native/plugins/window/src.d.ts +1 -0
  289. package/types/vendor/@akanjs/native/plugins/window-state/src/desktop.d.ts +7 -0
  290. package/types/vendor/@akanjs/native/plugins/window-state/src/index.d.ts +33 -0
  291. package/types/vendor/@akanjs/native/plugins/window-state/src/state.d.ts +39 -0
  292. package/types/vendor/@akanjs/native/plugins/window-state/src.d.ts +1 -0
  293. package/types/webkit/index.d.ts +0 -2
  294. package/types/webkit/nativeNavigation.d.ts +25 -0
  295. package/types/webkit/nativePurchase.d.ts +37 -0
  296. package/types/webkit/useCamera.d.ts +13 -15
  297. package/types/webkit/useGeoLocation.d.ts +4 -5
  298. package/types/webkit/usePurchase.d.ts +12 -16
  299. package/ui/Link/Anchor.tsx +2 -5
  300. package/ui/System/Client.tsx +2 -6
  301. package/vendor/@akanjs/native/LICENSE +21 -0
  302. package/vendor/@akanjs/native/README.ko.md +88 -0
  303. package/vendor/@akanjs/native/README.md +93 -0
  304. package/vendor/@akanjs/native/THIRD_PARTY_NOTICES.md +237 -0
  305. package/vendor/@akanjs/native/native/android/maven.lock.json +1751 -0
  306. package/vendor/@akanjs/native/native/android/src/com/akanjs/runtime/AkanNativeAcl.kt +243 -0
  307. package/vendor/@akanjs/native/native/android/src/com/akanjs/runtime/AkanNativeActivity.kt +936 -0
  308. package/vendor/@akanjs/native/native/android/src/com/akanjs/runtime/AkanNativeApplication.kt +189 -0
  309. package/vendor/@akanjs/native/native/android/src/com/akanjs/runtime/AkanNativeAssetServer.kt +225 -0
  310. package/vendor/@akanjs/native/native/android/src/com/akanjs/runtime/AkanNativeBridge.kt +444 -0
  311. package/vendor/@akanjs/native/native/android/src/com/akanjs/runtime/AkanNativeCompat.kt +55 -0
  312. package/vendor/@akanjs/native/native/android/src/com/akanjs/runtime/AkanNativeContract.kt +99 -0
  313. package/vendor/@akanjs/native/native/android/src/com/akanjs/runtime/AkanNativeEd25519.kt +100 -0
  314. package/vendor/@akanjs/native/native/android/src/com/akanjs/runtime/AkanNativeFileProvider.kt +71 -0
  315. package/vendor/@akanjs/native/native/android/src/com/akanjs/runtime/AkanNativeKernel.kt +324 -0
  316. package/vendor/@akanjs/native/native/android/src/com/akanjs/runtime/AkanNativePlugin.kt +361 -0
  317. package/vendor/@akanjs/native/native/android/src/com/akanjs/runtime/AkanNativeSpec.kt +100 -0
  318. package/vendor/@akanjs/native/native/android/src/com/akanjs/runtime/AkanNativeUpdates.kt +305 -0
  319. package/vendor/@akanjs/native/native/android/src/com/akanjs/runtime/AkanNativeVectors.kt +132 -0
  320. package/vendor/@akanjs/native/native/desktop/Cargo.lock +2565 -0
  321. package/vendor/@akanjs/native/native/desktop/Cargo.toml +49 -0
  322. package/vendor/@akanjs/native/native/desktop/build.rs +19 -0
  323. package/vendor/@akanjs/native/native/desktop/rust-toolchain.toml +7 -0
  324. package/vendor/@akanjs/native/native/desktop/src/accelerator.rs +466 -0
  325. package/vendor/@akanjs/native/native/desktop/src/autostart.rs +158 -0
  326. package/vendor/@akanjs/native/native/desktop/src/camera.rs +53 -0
  327. package/vendor/@akanjs/native/native/desktop/src/chrome.rs +710 -0
  328. package/vendor/@akanjs/native/native/desktop/src/contract.rs +105 -0
  329. package/vendor/@akanjs/native/native/desktop/src/devproxy.rs +234 -0
  330. package/vendor/@akanjs/native/native/desktop/src/dialog_args.rs +189 -0
  331. package/vendor/@akanjs/native/native/desktop/src/dock.rs +209 -0
  332. package/vendor/@akanjs/native/native/desktop/src/hotkey.rs +209 -0
  333. package/vendor/@akanjs/native/native/desktop/src/js_panels.rs +125 -0
  334. package/vendor/@akanjs/native/native/desktop/src/json.rs +272 -0
  335. package/vendor/@akanjs/native/native/desktop/src/keychain.rs +151 -0
  336. package/vendor/@akanjs/native/native/desktop/src/lib.rs +2185 -0
  337. package/vendor/@akanjs/native/native/desktop/src/linux/appearance.rs +177 -0
  338. package/vendor/@akanjs/native/native/desktop/src/linux/camera.rs +11 -0
  339. package/vendor/@akanjs/native/native/desktop/src/linux/clipboard.rs +48 -0
  340. package/vendor/@akanjs/native/native/desktop/src/linux/device.rs +9 -0
  341. package/vendor/@akanjs/native/native/desktop/src/linux/dialogs.rs +348 -0
  342. package/vendor/@akanjs/native/native/desktop/src/linux/dock.rs +146 -0
  343. package/vendor/@akanjs/native/native/desktop/src/linux/hotkey.rs +228 -0
  344. package/vendor/@akanjs/native/native/desktop/src/linux/keychain.rs +243 -0
  345. package/vendor/@akanjs/native/native/desktop/src/linux/menu.rs +445 -0
  346. package/vendor/@akanjs/native/native/desktop/src/linux/mod.rs +116 -0
  347. package/vendor/@akanjs/native/native/desktop/src/linux/notify.rs +211 -0
  348. package/vendor/@akanjs/native/native/desktop/src/linux/open.rs +79 -0
  349. package/vendor/@akanjs/native/native/desktop/src/linux/power.rs +155 -0
  350. package/vendor/@akanjs/native/native/desktop/src/linux/screen.rs +158 -0
  351. package/vendor/@akanjs/native/native/desktop/src/linux/tray.rs +604 -0
  352. package/vendor/@akanjs/native/native/desktop/src/menu.rs +517 -0
  353. package/vendor/@akanjs/native/native/desktop/src/navigation.rs +381 -0
  354. package/vendor/@akanjs/native/native/desktop/src/notify.rs +411 -0
  355. package/vendor/@akanjs/native/native/desktop/src/notify_schedule.rs +382 -0
  356. package/vendor/@akanjs/native/native/desktop/src/page_menu.rs +287 -0
  357. package/vendor/@akanjs/native/native/desktop/src/panels.rs +333 -0
  358. package/vendor/@akanjs/native/native/desktop/src/placement.rs +92 -0
  359. package/vendor/@akanjs/native/native/desktop/src/routes.rs +153 -0
  360. package/vendor/@akanjs/native/native/desktop/src/screen.rs +190 -0
  361. package/vendor/@akanjs/native/native/desktop/src/tray.rs +279 -0
  362. package/vendor/@akanjs/native/native/desktop/src/vectors.rs +126 -0
  363. package/vendor/@akanjs/native/native/desktop/src/win/appearance.rs +51 -0
  364. package/vendor/@akanjs/native/native/desktop/src/win/autostart.rs +77 -0
  365. package/vendor/@akanjs/native/native/desktop/src/win/camera.rs +34 -0
  366. package/vendor/@akanjs/native/native/desktop/src/win/clipboard.rs +106 -0
  367. package/vendor/@akanjs/native/native/desktop/src/win/device.rs +80 -0
  368. package/vendor/@akanjs/native/native/desktop/src/win/dialogs.rs +917 -0
  369. package/vendor/@akanjs/native/native/desktop/src/win/dock.rs +228 -0
  370. package/vendor/@akanjs/native/native/desktop/src/win/hotkey.rs +110 -0
  371. package/vendor/@akanjs/native/native/desktop/src/win/keychain.rs +103 -0
  372. package/vendor/@akanjs/native/native/desktop/src/win/menu.rs +500 -0
  373. package/vendor/@akanjs/native/native/desktop/src/win/mod.rs +100 -0
  374. package/vendor/@akanjs/native/native/desktop/src/win/msgwin.rs +86 -0
  375. package/vendor/@akanjs/native/native/desktop/src/win/notify.rs +334 -0
  376. package/vendor/@akanjs/native/native/desktop/src/win/open.rs +127 -0
  377. package/vendor/@akanjs/native/native/desktop/src/win/power.rs +64 -0
  378. package/vendor/@akanjs/native/native/desktop/src/win/registry.rs +87 -0
  379. package/vendor/@akanjs/native/native/desktop/src/win/screen.rs +127 -0
  380. package/vendor/@akanjs/native/native/desktop/src/win/tray.rs +280 -0
  381. package/vendor/@akanjs/native/native/ios/Sources/AkanNativeAcl.swift +241 -0
  382. package/vendor/@akanjs/native/native/ios/Sources/AkanNativeApp.swift +285 -0
  383. package/vendor/@akanjs/native/native/ios/Sources/AkanNativeBridge.swift +407 -0
  384. package/vendor/@akanjs/native/native/ios/Sources/AkanNativeContract.swift +106 -0
  385. package/vendor/@akanjs/native/native/ios/Sources/AkanNativeKernel.swift +317 -0
  386. package/vendor/@akanjs/native/native/ios/Sources/AkanNativePlugin.swift +250 -0
  387. package/vendor/@akanjs/native/native/ios/Sources/AkanNativeSchemeHandler.swift +209 -0
  388. package/vendor/@akanjs/native/native/ios/Sources/AkanNativeShell.swift +161 -0
  389. package/vendor/@akanjs/native/native/ios/Sources/AkanNativeSpec.swift +143 -0
  390. package/vendor/@akanjs/native/native/ios/Sources/AkanNativeUpdates.swift +270 -0
  391. package/vendor/@akanjs/native/native/ios/Sources/AkanNativeVectors.swift +155 -0
  392. package/vendor/@akanjs/native/native/ios/Sources/AkanNativeViewController.swift +371 -0
  393. package/vendor/@akanjs/native/packages/cli/src/api.ts +600 -0
  394. package/vendor/@akanjs/native/packages/cli/src/commands/build.ts +101 -0
  395. package/vendor/@akanjs/native/packages/cli/src/commands/compat.ts +53 -0
  396. package/vendor/@akanjs/native/packages/cli/src/commands/dev.ts +249 -0
  397. package/vendor/@akanjs/native/packages/cli/src/commands/doctor.ts +536 -0
  398. package/vendor/@akanjs/native/packages/cli/src/commands/plugin.ts +164 -0
  399. package/vendor/@akanjs/native/packages/cli/src/commands/signing.ts +32 -0
  400. package/vendor/@akanjs/native/packages/cli/src/commands/test.ts +130 -0
  401. package/vendor/@akanjs/native/packages/cli/src/commands/toolchain.ts +143 -0
  402. package/vendor/@akanjs/native/packages/cli/src/commands/update.ts +168 -0
  403. package/vendor/@akanjs/native/packages/cli/src/config.ts +257 -0
  404. package/vendor/@akanjs/native/packages/cli/src/index.ts +77 -0
  405. package/vendor/@akanjs/native/packages/cli/src/lib/acl.ts +420 -0
  406. package/vendor/@akanjs/native/packages/cli/src/lib/apilevel.ts +245 -0
  407. package/vendor/@akanjs/native/packages/cli/src/lib/apk.ts +203 -0
  408. package/vendor/@akanjs/native/packages/cli/src/lib/args.ts +44 -0
  409. package/vendor/@akanjs/native/packages/cli/src/lib/boot.ts +73 -0
  410. package/vendor/@akanjs/native/packages/cli/src/lib/chrome.ts +89 -0
  411. package/vendor/@akanjs/native/packages/cli/src/lib/codegen.ts +1128 -0
  412. package/vendor/@akanjs/native/packages/cli/src/lib/compat.ts +185 -0
  413. package/vendor/@akanjs/native/packages/cli/src/lib/configkeys.ts +91 -0
  414. package/vendor/@akanjs/native/packages/cli/src/lib/csp.ts +198 -0
  415. package/vendor/@akanjs/native/packages/cli/src/lib/env.ts +257 -0
  416. package/vendor/@akanjs/native/packages/cli/src/lib/exec.ts +104 -0
  417. package/vendor/@akanjs/native/packages/cli/src/lib/googleservices.ts +53 -0
  418. package/vendor/@akanjs/native/packages/cli/src/lib/hmr.ts +534 -0
  419. package/vendor/@akanjs/native/packages/cli/src/lib/html.ts +63 -0
  420. package/vendor/@akanjs/native/packages/cli/src/lib/icons.ts +316 -0
  421. package/vendor/@akanjs/native/packages/cli/src/lib/image.ts +175 -0
  422. package/vendor/@akanjs/native/packages/cli/src/lib/iossigning.ts +295 -0
  423. package/vendor/@akanjs/native/packages/cli/src/lib/launch.ts +98 -0
  424. package/vendor/@akanjs/native/packages/cli/src/lib/log.ts +105 -0
  425. package/vendor/@akanjs/native/packages/cli/src/lib/manifestmerge.ts +107 -0
  426. package/vendor/@akanjs/native/packages/cli/src/lib/maven.ts +244 -0
  427. package/vendor/@akanjs/native/packages/cli/src/lib/names.ts +202 -0
  428. package/vendor/@akanjs/native/packages/cli/src/lib/native-plugins.ts +326 -0
  429. package/vendor/@akanjs/native/packages/cli/src/lib/nativeconfig.ts +68 -0
  430. package/vendor/@akanjs/native/packages/cli/src/lib/permissions.ts +80 -0
  431. package/vendor/@akanjs/native/packages/cli/src/lib/plist.ts +139 -0
  432. package/vendor/@akanjs/native/packages/cli/src/lib/png.ts +240 -0
  433. package/vendor/@akanjs/native/packages/cli/src/lib/prepare.ts +290 -0
  434. package/vendor/@akanjs/native/packages/cli/src/lib/privacy.ts +64 -0
  435. package/vendor/@akanjs/native/packages/cli/src/lib/project.ts +710 -0
  436. package/vendor/@akanjs/native/packages/cli/src/lib/root.ts +18 -0
  437. package/vendor/@akanjs/native/packages/cli/src/lib/routes.ts +3 -0
  438. package/vendor/@akanjs/native/packages/cli/src/lib/serve.ts +83 -0
  439. package/vendor/@akanjs/native/packages/cli/src/lib/signing.ts +117 -0
  440. package/vendor/@akanjs/native/packages/cli/src/lib/spec.ts +521 -0
  441. package/vendor/@akanjs/native/packages/cli/src/lib/toolchains.ts +579 -0
  442. package/vendor/@akanjs/native/packages/cli/src/lib/updates.ts +160 -0
  443. package/vendor/@akanjs/native/packages/cli/src/lib/vectors.ts +121 -0
  444. package/vendor/@akanjs/native/packages/cli/src/lib/xml.ts +72 -0
  445. package/vendor/@akanjs/native/packages/cli/src/platforms/android.ts +1320 -0
  446. package/vendor/@akanjs/native/packages/cli/src/platforms/desktop-update.ts +78 -0
  447. package/vendor/@akanjs/native/packages/cli/src/platforms/desktop.ts +279 -0
  448. package/vendor/@akanjs/native/packages/cli/src/platforms/index.ts +31 -0
  449. package/vendor/@akanjs/native/packages/cli/src/platforms/ios.ts +801 -0
  450. package/vendor/@akanjs/native/packages/cli/src/platforms/linux.ts +52 -0
  451. package/vendor/@akanjs/native/packages/cli/src/platforms/macos.ts +97 -0
  452. package/vendor/@akanjs/native/packages/cli/src/platforms/targets.ts +12 -0
  453. package/vendor/@akanjs/native/packages/cli/src/platforms/web-run.ts +69 -0
  454. package/vendor/@akanjs/native/packages/cli/src/platforms/web.ts +28 -0
  455. package/vendor/@akanjs/native/packages/cli/src/platforms/windows.ts +82 -0
  456. package/vendor/@akanjs/native/packages/core/contract.json +96 -0
  457. package/vendor/@akanjs/native/packages/core/src/acl.ts +272 -0
  458. package/vendor/@akanjs/native/packages/core/src/boot.ts +97 -0
  459. package/vendor/@akanjs/native/packages/core/src/contract.ts +100 -0
  460. package/vendor/@akanjs/native/packages/core/src/errors.ts +95 -0
  461. package/vendor/@akanjs/native/packages/core/src/files.ts +105 -0
  462. package/vendor/@akanjs/native/packages/core/src/index.ts +35 -0
  463. package/vendor/@akanjs/native/packages/core/src/kernel.ts +281 -0
  464. package/vendor/@akanjs/native/packages/core/src/live.ts +62 -0
  465. package/vendor/@akanjs/native/packages/core/src/mime.ts +8 -0
  466. package/vendor/@akanjs/native/packages/core/src/plugin.ts +358 -0
  467. package/vendor/@akanjs/native/packages/core/src/protocol.ts +194 -0
  468. package/vendor/@akanjs/native/packages/core/src/runtime.ts +520 -0
  469. package/vendor/@akanjs/native/packages/core/src/state.ts +46 -0
  470. package/vendor/@akanjs/native/packages/core/src/testing.ts +176 -0
  471. package/vendor/@akanjs/native/packages/core/src/version.ts +2 -0
  472. package/vendor/@akanjs/native/packages/core/src/veto.ts +55 -0
  473. package/vendor/@akanjs/native/packages/core/vectors/acl.json +57 -0
  474. package/vendor/@akanjs/native/packages/core/vectors/bridge.json +76 -0
  475. package/vendor/@akanjs/native/packages/core/vectors/ed25519.json +29 -0
  476. package/vendor/@akanjs/native/packages/core/vectors/ids.json +73 -0
  477. package/vendor/@akanjs/native/packages/core/vectors/navigation.json +75 -0
  478. package/vendor/@akanjs/native/packages/core/vectors/ranges.json +39 -0
  479. package/vendor/@akanjs/native/packages/core/vectors/retained.json +17 -0
  480. package/vendor/@akanjs/native/packages/core/vectors/routes.json +66 -0
  481. package/vendor/@akanjs/native/packages/core/vectors/scope.json +143 -0
  482. package/vendor/@akanjs/native/packages/desktop/src/deeplinks.ts +143 -0
  483. package/vendor/@akanjs/native/packages/desktop/src/delta.ts +174 -0
  484. package/vendor/@akanjs/native/packages/desktop/src/dispatcher.ts +679 -0
  485. package/vendor/@akanjs/native/packages/desktop/src/ffi.ts +76 -0
  486. package/vendor/@akanjs/native/packages/desktop/src/host.ts +355 -0
  487. package/vendor/@akanjs/native/packages/desktop/src/lifecycle.ts +142 -0
  488. package/vendor/@akanjs/native/packages/desktop/src/main.ts +133 -0
  489. package/vendor/@akanjs/native/packages/desktop/src/page-veto.ts +103 -0
  490. package/vendor/@akanjs/native/packages/desktop/src/paths.ts +59 -0
  491. package/vendor/@akanjs/native/packages/desktop/src/plugin.ts +232 -0
  492. package/vendor/@akanjs/native/packages/react/src/index.ts +23 -0
  493. package/vendor/@akanjs/native/plugins/accessibility/android/AccessibilityPlugin.kt +96 -0
  494. package/vendor/@akanjs/native/plugins/accessibility/ios/AccessibilityPlugin.swift +92 -0
  495. package/vendor/@akanjs/native/plugins/accessibility/native-plugin.json +21 -0
  496. package/vendor/@akanjs/native/plugins/accessibility/src/announce.ts +71 -0
  497. package/vendor/@akanjs/native/plugins/accessibility/src/index.ts +77 -0
  498. package/vendor/@akanjs/native/plugins/accessibility/src/web.ts +52 -0
  499. package/vendor/@akanjs/native/plugins/app/android/AppPlugin.kt +72 -0
  500. package/vendor/@akanjs/native/plugins/app/ios/AppPlugin.swift +52 -0
  501. package/vendor/@akanjs/native/plugins/app/native-plugin.json +21 -0
  502. package/vendor/@akanjs/native/plugins/app/src/desktop.ts +64 -0
  503. package/vendor/@akanjs/native/plugins/app/src/index.ts +77 -0
  504. package/vendor/@akanjs/native/plugins/app/src/web.ts +12 -0
  505. package/vendor/@akanjs/native/plugins/app-state/android/AppStatePlugin.kt +54 -0
  506. package/vendor/@akanjs/native/plugins/app-state/ios/AppStatePlugin.swift +58 -0
  507. package/vendor/@akanjs/native/plugins/app-state/native-plugin.json +17 -0
  508. package/vendor/@akanjs/native/plugins/app-state/src/index.ts +42 -0
  509. package/vendor/@akanjs/native/plugins/app-state/src/web.ts +33 -0
  510. package/vendor/@akanjs/native/plugins/appearance/android/AppearancePlugin.kt +133 -0
  511. package/vendor/@akanjs/native/plugins/appearance/ios/AppearancePlugin.swift +109 -0
  512. package/vendor/@akanjs/native/plugins/appearance/native-plugin.json +18 -0
  513. package/vendor/@akanjs/native/plugins/appearance/src/desktop.ts +133 -0
  514. package/vendor/@akanjs/native/plugins/appearance/src/index.ts +62 -0
  515. package/vendor/@akanjs/native/plugins/appearance/src/setting.ts +18 -0
  516. package/vendor/@akanjs/native/plugins/appearance/src/web.ts +25 -0
  517. package/vendor/@akanjs/native/plugins/auth-session/android/AuthSessionPlugin.kt +171 -0
  518. package/vendor/@akanjs/native/plugins/auth-session/ios/AuthSessionPlugin.swift +112 -0
  519. package/vendor/@akanjs/native/plugins/auth-session/native-plugin.json +19 -0
  520. package/vendor/@akanjs/native/plugins/auth-session/src/args.ts +62 -0
  521. package/vendor/@akanjs/native/plugins/auth-session/src/desktop.ts +133 -0
  522. package/vendor/@akanjs/native/plugins/auth-session/src/index.ts +39 -0
  523. package/vendor/@akanjs/native/plugins/autostart/native-plugin.json +10 -0
  524. package/vendor/@akanjs/native/plugins/autostart/src/desktop.ts +189 -0
  525. package/vendor/@akanjs/native/plugins/autostart/src/index.ts +51 -0
  526. package/vendor/@akanjs/native/plugins/badge/ios/BadgePlugin.swift +92 -0
  527. package/vendor/@akanjs/native/plugins/badge/native-plugin.json +15 -0
  528. package/vendor/@akanjs/native/plugins/badge/src/count.ts +12 -0
  529. package/vendor/@akanjs/native/plugins/badge/src/desktop.ts +24 -0
  530. package/vendor/@akanjs/native/plugins/badge/src/index.ts +40 -0
  531. package/vendor/@akanjs/native/plugins/badge/src/web.ts +37 -0
  532. package/vendor/@akanjs/native/plugins/biometric/android/BiometricPlugin.kt +179 -0
  533. package/vendor/@akanjs/native/plugins/biometric/ios/BiometricPlugin.swift +129 -0
  534. package/vendor/@akanjs/native/plugins/biometric/native-plugin.json +22 -0
  535. package/vendor/@akanjs/native/plugins/biometric/src/index.ts +100 -0
  536. package/vendor/@akanjs/native/plugins/browser/android/BrowserPlugin.kt +178 -0
  537. package/vendor/@akanjs/native/plugins/browser/ios/BrowserPlugin.swift +63 -0
  538. package/vendor/@akanjs/native/plugins/browser/native-plugin.json +22 -0
  539. package/vendor/@akanjs/native/plugins/browser/src/args.ts +34 -0
  540. package/vendor/@akanjs/native/plugins/browser/src/desktop.ts +40 -0
  541. package/vendor/@akanjs/native/plugins/browser/src/index.ts +47 -0
  542. package/vendor/@akanjs/native/plugins/browser/src/web.ts +60 -0
  543. package/vendor/@akanjs/native/plugins/camera/android/CameraPlugin.kt +365 -0
  544. package/vendor/@akanjs/native/plugins/camera/ios/CameraPlugin.swift +296 -0
  545. package/vendor/@akanjs/native/plugins/camera/native-plugin.json +32 -0
  546. package/vendor/@akanjs/native/plugins/camera/src/desktop.ts +27 -0
  547. package/vendor/@akanjs/native/plugins/camera/src/index.ts +85 -0
  548. package/vendor/@akanjs/native/plugins/camera/src/web.ts +267 -0
  549. package/vendor/@akanjs/native/plugins/clipboard/android/ClipboardPlugin.kt +51 -0
  550. package/vendor/@akanjs/native/plugins/clipboard/ios/ClipboardPlugin.swift +35 -0
  551. package/vendor/@akanjs/native/plugins/clipboard/native-plugin.json +17 -0
  552. package/vendor/@akanjs/native/plugins/clipboard/src/desktop.ts +66 -0
  553. package/vendor/@akanjs/native/plugins/clipboard/src/index.ts +72 -0
  554. package/vendor/@akanjs/native/plugins/clipboard/src/web.ts +69 -0
  555. package/vendor/@akanjs/native/plugins/device/android/DevicePlugin.kt +70 -0
  556. package/vendor/@akanjs/native/plugins/device/ios/DevicePlugin.swift +80 -0
  557. package/vendor/@akanjs/native/plugins/device/native-plugin.json +18 -0
  558. package/vendor/@akanjs/native/plugins/device/src/desktop.ts +276 -0
  559. package/vendor/@akanjs/native/plugins/device/src/index.ts +72 -0
  560. package/vendor/@akanjs/native/plugins/device/src/web.ts +162 -0
  561. package/vendor/@akanjs/native/plugins/dialog/android/DialogPlugin.kt +260 -0
  562. package/vendor/@akanjs/native/plugins/dialog/ios/DialogPlugin.swift +198 -0
  563. package/vendor/@akanjs/native/plugins/dialog/native-plugin.json +18 -0
  564. package/vendor/@akanjs/native/plugins/dialog/src/desktop.ts +80 -0
  565. package/vendor/@akanjs/native/plugins/dialog/src/index.ts +87 -0
  566. package/vendor/@akanjs/native/plugins/dialog/src/options.ts +111 -0
  567. package/vendor/@akanjs/native/plugins/dialog/src/web.ts +296 -0
  568. package/vendor/@akanjs/native/plugins/dock/native-plugin.json +10 -0
  569. package/vendor/@akanjs/native/plugins/dock/src/desktop.ts +34 -0
  570. package/vendor/@akanjs/native/plugins/dock/src/index.ts +46 -0
  571. package/vendor/@akanjs/native/plugins/file-picker/android/FilePickerPlugin.kt +316 -0
  572. package/vendor/@akanjs/native/plugins/file-picker/ios/FilePickerPlugin.swift +366 -0
  573. package/vendor/@akanjs/native/plugins/file-picker/native-plugin.json +18 -0
  574. package/vendor/@akanjs/native/plugins/file-picker/src/common.ts +125 -0
  575. package/vendor/@akanjs/native/plugins/file-picker/src/desktop.ts +164 -0
  576. package/vendor/@akanjs/native/plugins/file-picker/src/index.ts +187 -0
  577. package/vendor/@akanjs/native/plugins/file-picker/src/web.ts +158 -0
  578. package/vendor/@akanjs/native/plugins/filesystem/android/FilesystemPlugin.kt +561 -0
  579. package/vendor/@akanjs/native/plugins/filesystem/ios/FilesystemPlugin.swift +596 -0
  580. package/vendor/@akanjs/native/plugins/filesystem/native-plugin.json +45 -0
  581. package/vendor/@akanjs/native/plugins/filesystem/src/common.ts +150 -0
  582. package/vendor/@akanjs/native/plugins/filesystem/src/desktop.ts +438 -0
  583. package/vendor/@akanjs/native/plugins/filesystem/src/index.ts +179 -0
  584. package/vendor/@akanjs/native/plugins/filesystem/src/web.ts +334 -0
  585. package/vendor/@akanjs/native/plugins/geolocation/android/GeolocationPlugin.kt +360 -0
  586. package/vendor/@akanjs/native/plugins/geolocation/ios/GeolocationPlugin.swift +284 -0
  587. package/vendor/@akanjs/native/plugins/geolocation/native-plugin.json +23 -0
  588. package/vendor/@akanjs/native/plugins/geolocation/src/index.ts +155 -0
  589. package/vendor/@akanjs/native/plugins/geolocation/src/web.ts +132 -0
  590. package/vendor/@akanjs/native/plugins/global-shortcut/native-plugin.json +10 -0
  591. package/vendor/@akanjs/native/plugins/global-shortcut/src/desktop.ts +36 -0
  592. package/vendor/@akanjs/native/plugins/global-shortcut/src/index.ts +55 -0
  593. package/vendor/@akanjs/native/plugins/haptics/android/HapticsPlugin.kt +127 -0
  594. package/vendor/@akanjs/native/plugins/haptics/ios/HapticsPlugin.swift +127 -0
  595. package/vendor/@akanjs/native/plugins/haptics/native-plugin.json +19 -0
  596. package/vendor/@akanjs/native/plugins/haptics/src/index.ts +34 -0
  597. package/vendor/@akanjs/native/plugins/haptics/src/web.ts +53 -0
  598. package/vendor/@akanjs/native/plugins/http/android/HttpPlugin.kt +234 -0
  599. package/vendor/@akanjs/native/plugins/http/android/HttpUrl.kt +182 -0
  600. package/vendor/@akanjs/native/plugins/http/ios/HttpPlugin.swift +228 -0
  601. package/vendor/@akanjs/native/plugins/http/ios/HttpUrl.swift +166 -0
  602. package/vendor/@akanjs/native/plugins/http/native-plugin.json +27 -0
  603. package/vendor/@akanjs/native/plugins/http/src/common.ts +294 -0
  604. package/vendor/@akanjs/native/plugins/http/src/desktop.ts +69 -0
  605. package/vendor/@akanjs/native/plugins/http/src/index.ts +181 -0
  606. package/vendor/@akanjs/native/plugins/http/src/web.ts +40 -0
  607. package/vendor/@akanjs/native/plugins/iap/android/IapPlugin.kt +358 -0
  608. package/vendor/@akanjs/native/plugins/iap/ios/IapPlugin.swift +306 -0
  609. package/vendor/@akanjs/native/plugins/iap/native-plugin.json +28 -0
  610. package/vendor/@akanjs/native/plugins/iap/src/index.ts +206 -0
  611. package/vendor/@akanjs/native/plugins/keep-awake/android/KeepAwakePlugin.kt +48 -0
  612. package/vendor/@akanjs/native/plugins/keep-awake/ios/KeepAwakePlugin.swift +36 -0
  613. package/vendor/@akanjs/native/plugins/keep-awake/native-plugin.json +17 -0
  614. package/vendor/@akanjs/native/plugins/keep-awake/src/desktop.ts +127 -0
  615. package/vendor/@akanjs/native/plugins/keep-awake/src/index.ts +79 -0
  616. package/vendor/@akanjs/native/plugins/keep-awake/src/web.ts +78 -0
  617. package/vendor/@akanjs/native/plugins/keyboard/android/KeyboardPlugin.kt +77 -0
  618. package/vendor/@akanjs/native/plugins/keyboard/ios/KeyboardPlugin.swift +93 -0
  619. package/vendor/@akanjs/native/plugins/keyboard/native-plugin.json +18 -0
  620. package/vendor/@akanjs/native/plugins/keyboard/src/index.ts +78 -0
  621. package/vendor/@akanjs/native/plugins/keyboard/src/web.ts +57 -0
  622. package/vendor/@akanjs/native/plugins/local-notifications/android/LocalNotificationReceiver.kt +38 -0
  623. package/vendor/@akanjs/native/plugins/local-notifications/android/LocalNotifications.kt +284 -0
  624. package/vendor/@akanjs/native/plugins/local-notifications/android/LocalNotificationsPlugin.kt +248 -0
  625. package/vendor/@akanjs/native/plugins/local-notifications/ios/LocalNotificationsPlugin.swift +279 -0
  626. package/vendor/@akanjs/native/plugins/local-notifications/native-plugin.json +35 -0
  627. package/vendor/@akanjs/native/plugins/local-notifications/src/desktop.ts +196 -0
  628. package/vendor/@akanjs/native/plugins/local-notifications/src/index.ts +174 -0
  629. package/vendor/@akanjs/native/plugins/local-notifications/src/schedule.ts +164 -0
  630. package/vendor/@akanjs/native/plugins/local-notifications/src/timers.ts +72 -0
  631. package/vendor/@akanjs/native/plugins/local-notifications/src/web.ts +158 -0
  632. package/vendor/@akanjs/native/plugins/menu/native-plugin.json +10 -0
  633. package/vendor/@akanjs/native/plugins/menu/src/desktop.ts +52 -0
  634. package/vendor/@akanjs/native/plugins/menu/src/index.ts +107 -0
  635. package/vendor/@akanjs/native/plugins/network/android/NetworkPlugin.kt +124 -0
  636. package/vendor/@akanjs/native/plugins/network/ios/NetworkPlugin.swift +82 -0
  637. package/vendor/@akanjs/native/plugins/network/native-plugin.json +19 -0
  638. package/vendor/@akanjs/native/plugins/network/src/index.ts +59 -0
  639. package/vendor/@akanjs/native/plugins/network/src/web.ts +43 -0
  640. package/vendor/@akanjs/native/plugins/opener/android/OpenerPlugin.kt +81 -0
  641. package/vendor/@akanjs/native/plugins/opener/ios/OpenerPlugin.swift +83 -0
  642. package/vendor/@akanjs/native/plugins/opener/native-plugin.json +25 -0
  643. package/vendor/@akanjs/native/plugins/opener/src/desktop.ts +88 -0
  644. package/vendor/@akanjs/native/plugins/opener/src/index.ts +35 -0
  645. package/vendor/@akanjs/native/plugins/opener/src/url.ts +39 -0
  646. package/vendor/@akanjs/native/plugins/opener/src/web.ts +33 -0
  647. package/vendor/@akanjs/native/plugins/preferences/android/PreferencesPlugin.kt +44 -0
  648. package/vendor/@akanjs/native/plugins/preferences/ios/PreferencesPlugin.swift +47 -0
  649. package/vendor/@akanjs/native/plugins/preferences/native-plugin.json +18 -0
  650. package/vendor/@akanjs/native/plugins/preferences/src/desktop.ts +59 -0
  651. package/vendor/@akanjs/native/plugins/preferences/src/index.ts +75 -0
  652. package/vendor/@akanjs/native/plugins/preferences/src/web.ts +55 -0
  653. package/vendor/@akanjs/native/plugins/push/android/AkanNativeMessagingService.kt +17 -0
  654. package/vendor/@akanjs/native/plugins/push/android/PushPlugin.kt +257 -0
  655. package/vendor/@akanjs/native/plugins/push/ios/PushPlugin.swift +169 -0
  656. package/vendor/@akanjs/native/plugins/push/native-plugin.json +23 -0
  657. package/vendor/@akanjs/native/plugins/push/src/index.ts +73 -0
  658. package/vendor/@akanjs/native/plugins/screen/native-plugin.json +10 -0
  659. package/vendor/@akanjs/native/plugins/screen/src/desktop.ts +50 -0
  660. package/vendor/@akanjs/native/plugins/screen/src/index.ts +107 -0
  661. package/vendor/@akanjs/native/plugins/screen/src/web.ts +92 -0
  662. package/vendor/@akanjs/native/plugins/screen-orientation/android/ScreenOrientationPlugin.kt +113 -0
  663. package/vendor/@akanjs/native/plugins/screen-orientation/ios/ScreenOrientationPlugin.swift +150 -0
  664. package/vendor/@akanjs/native/plugins/screen-orientation/native-plugin.json +17 -0
  665. package/vendor/@akanjs/native/plugins/screen-orientation/src/index.ts +69 -0
  666. package/vendor/@akanjs/native/plugins/screen-orientation/src/types.ts +26 -0
  667. package/vendor/@akanjs/native/plugins/screen-orientation/src/web.ts +67 -0
  668. package/vendor/@akanjs/native/plugins/secure-storage/android/SecureStoragePlugin.kt +184 -0
  669. package/vendor/@akanjs/native/plugins/secure-storage/ios/SecureStoragePlugin.swift +145 -0
  670. package/vendor/@akanjs/native/plugins/secure-storage/native-plugin.json +18 -0
  671. package/vendor/@akanjs/native/plugins/secure-storage/src/desktop.ts +332 -0
  672. package/vendor/@akanjs/native/plugins/secure-storage/src/index.ts +33 -0
  673. package/vendor/@akanjs/native/plugins/share/android/SharePlugin.kt +218 -0
  674. package/vendor/@akanjs/native/plugins/share/ios/SharePlugin.swift +142 -0
  675. package/vendor/@akanjs/native/plugins/share/native-plugin.json +18 -0
  676. package/vendor/@akanjs/native/plugins/share/src/index.ts +87 -0
  677. package/vendor/@akanjs/native/plugins/share/src/options.ts +43 -0
  678. package/vendor/@akanjs/native/plugins/share/src/web.ts +116 -0
  679. package/vendor/@akanjs/native/plugins/single-instance/native-plugin.json +10 -0
  680. package/vendor/@akanjs/native/plugins/single-instance/src/desktop.ts +63 -0
  681. package/vendor/@akanjs/native/plugins/single-instance/src/index.ts +32 -0
  682. package/vendor/@akanjs/native/plugins/single-instance/src/socket.ts +248 -0
  683. package/vendor/@akanjs/native/plugins/splash-screen/android/SplashScreenPlugin.kt +19 -0
  684. package/vendor/@akanjs/native/plugins/splash-screen/ios/SplashScreenPlugin.swift +20 -0
  685. package/vendor/@akanjs/native/plugins/splash-screen/native-plugin.json +17 -0
  686. package/vendor/@akanjs/native/plugins/splash-screen/src/index.ts +24 -0
  687. package/vendor/@akanjs/native/plugins/splash-screen/src/web.ts +17 -0
  688. package/vendor/@akanjs/native/plugins/sqlite/android/SqlStatements.kt +121 -0
  689. package/vendor/@akanjs/native/plugins/sqlite/android/SqlitePlugin.kt +327 -0
  690. package/vendor/@akanjs/native/plugins/sqlite/ios/SqlitePlugin.swift +361 -0
  691. package/vendor/@akanjs/native/plugins/sqlite/native-plugin.json +18 -0
  692. package/vendor/@akanjs/native/plugins/sqlite/src/common.ts +221 -0
  693. package/vendor/@akanjs/native/plugins/sqlite/src/desktop.ts +140 -0
  694. package/vendor/@akanjs/native/plugins/sqlite/src/index.ts +114 -0
  695. package/vendor/@akanjs/native/plugins/toast/android/ToastPlugin.kt +27 -0
  696. package/vendor/@akanjs/native/plugins/toast/native-plugin.json +14 -0
  697. package/vendor/@akanjs/native/plugins/toast/src/index.ts +41 -0
  698. package/vendor/@akanjs/native/plugins/toast/src/queue.ts +77 -0
  699. package/vendor/@akanjs/native/plugins/toast/src/web.ts +130 -0
  700. package/vendor/@akanjs/native/plugins/tray/native-plugin.json +10 -0
  701. package/vendor/@akanjs/native/plugins/tray/src/desktop.ts +73 -0
  702. package/vendor/@akanjs/native/plugins/tray/src/index.ts +111 -0
  703. package/vendor/@akanjs/native/plugins/updates/android/UpdatesPlugin.kt +290 -0
  704. package/vendor/@akanjs/native/plugins/updates/ios/UpdatesPlugin.swift +292 -0
  705. package/vendor/@akanjs/native/plugins/updates/native-plugin.json +19 -0
  706. package/vendor/@akanjs/native/plugins/updates/src/desktop.ts +558 -0
  707. package/vendor/@akanjs/native/plugins/updates/src/index.ts +95 -0
  708. package/vendor/@akanjs/native/plugins/window/native-plugin.json +32 -0
  709. package/vendor/@akanjs/native/plugins/window/src/desktop.ts +170 -0
  710. package/vendor/@akanjs/native/plugins/window/src/index.ts +342 -0
  711. package/vendor/@akanjs/native/plugins/window/src/web.ts +43 -0
  712. package/vendor/@akanjs/native/plugins/window-state/native-plugin.json +10 -0
  713. package/vendor/@akanjs/native/plugins/window-state/src/desktop.ts +73 -0
  714. package/vendor/@akanjs/native/plugins/window-state/src/index.ts +35 -0
  715. package/vendor/@akanjs/native/plugins/window-state/src/state.ts +146 -0
  716. package/webkit/bootCsr.tsx +26 -14
  717. package/webkit/index.ts +0 -2
  718. package/webkit/nativeNavigation.ts +116 -0
  719. package/webkit/nativePurchase.ts +93 -0
  720. package/webkit/useCamera.tsx +76 -71
  721. package/webkit/useCsrValues.ts +10 -124
  722. package/webkit/useGeoLocation.tsx +11 -13
  723. package/webkit/usePurchase.tsx +68 -123
  724. package/capacitor.base.config.ts +0 -140
  725. package/client/capacitor.ts +0 -252
  726. package/types/capacitor.base.config.d.ts +0 -3
  727. package/types/client/capacitor.d.ts +0 -290
  728. package/types/webkit/useCodepush.d.ts +0 -16
  729. package/types/webkit/useContact.d.ts +0 -11
  730. package/webkit/useCodepush.tsx +0 -76
  731. package/webkit/useContact.tsx +0 -45
@@ -0,0 +1,917 @@
1
+ //! Native dialogs on Windows for the dialog and file-picker plugins, with the ops and JSON of the
2
+ //! macOS sheets (panels.rs, dialog_args.rs): `alert.show` → a TaskDialog (a dialog of our own when
3
+ //! it needs a text field), `panel.open` and `panel.save` → IFileOpenDialog / IFileSaveDialog,
4
+ //! `panel.mime` → the registry's Content Type. And D7 (JavaScript alert/confirm/prompt) under tests.
5
+ //!
6
+ //! - Each dialog runs on a thread of its own, owned by the app window (Tauri does the same through
7
+ //! rfd: tauri-plugins-workspace/plugins/dialog/src/desktop.rs:142-150). A Win32 dialog runs a
8
+ //! nested modal loop, and inside tao's event handler that loop would hold back every other event
9
+ //! of the app, IPC responses included (tao buffers what arrives while the handler runs,
10
+ //! tao/src/platform_impl/windows/event_loop/runner.rs event_buffer). The owner is disabled while
11
+ //! the dialog is open, like under a sheet; the other windows keep working.
12
+ //! - Common Controls 6 (TaskDialogIndirect, themed buttons and text fields): the Bun executable has
13
+ //! no manifest, so build.rs embeds one into this DLL (resource 2, a dependency on
14
+ //! Microsoft.Windows.Common-Controls 6) and a dialog thread activates it (electrobun/package/src/
15
+ //! native/win/nativeWrapper.cpp showTaskDialogWithDllActivationContext). TaskDialogIndirect is
16
+ //! looked up at run time, so the DLL loads without it; alerts then use our own dialog as well.
17
+ //! - Types: extensions and MIME types become one "*.ext" filter (the registry's MIME database and a
18
+ //! table of common types); a type without a known extension turns the filter off, so a file is
19
+ //! never unpickable (the macOS rule). One filter, no "All files" choice, as on macOS.
20
+
21
+ use std::{
22
+ cell::RefCell,
23
+ collections::HashMap,
24
+ ffi::c_void,
25
+ sync::{LazyLock, Mutex, OnceLock},
26
+ };
27
+
28
+ use tao::platform::windows::WindowExtWindows;
29
+ use windows::core::{w, Interface, BOOL, HRESULT, HSTRING, PCWSTR, PWSTR};
30
+ use windows::Win32::Foundation::{ERROR_CANCELLED, HANDLE, HINSTANCE, HMODULE, HWND, LPARAM, RECT, S_OK, WPARAM};
31
+ use windows::Win32::Graphics::Gdi::{
32
+ CreateFontIndirectW, DeleteObject, DrawTextW, GetDC, GetObjectW, ReleaseDC, SelectObject, DRAW_TEXT_FORMAT, DT_CALCRECT, DT_EXPANDTABS, DT_NOPREFIX, DT_SINGLELINE, DT_WORDBREAK, FW_BOLD,
33
+ HFONT, LOGFONTW,
34
+ };
35
+ use windows::Win32::System::ApplicationInstallationAndServicing::{ActivateActCtx, CreateActCtxW, DeactivateActCtx, ReleaseActCtx, ACTCTXW};
36
+ use windows::Win32::System::Com::{CoCreateInstance, CoInitializeEx, CoTaskMemFree, CoUninitialize, CLSCTX_INPROC_SERVER, COINIT_APARTMENTTHREADED, COINIT_DISABLE_OLE1DDE};
37
+ use windows::Win32::System::LibraryLoader::{GetModuleHandleExW, GetProcAddress, LoadLibraryW, GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT};
38
+ use windows::Win32::System::Ole::IOleWindow;
39
+ use windows::Win32::System::Registry::{RegCloseKey, RegEnumKeyExW, RegOpenKeyExW, HKEY, HKEY_CLASSES_ROOT, KEY_READ};
40
+ use windows::Win32::UI::Controls::{
41
+ EM_SETCUEBANNER, EM_SETSEL, TASKDIALOGCONFIG, TASKDIALOG_BUTTON, TASKDIALOG_NOTIFICATIONS, TDF_ALLOW_DIALOG_CANCELLATION, TDF_CALLBACK_TIMER, TDF_POSITION_RELATIVE_TO_WINDOW, TDF_SIZE_TO_CONTENT, TDM_CLICK_BUTTON, TDN_CREATED, TDN_DESTROYED, TDN_TIMER,
42
+ };
43
+ use windows::Win32::UI::Shell::Common::COMDLG_FILTERSPEC;
44
+ use windows::Win32::UI::Shell::{
45
+ FileOpenDialog, FileSaveDialog, IFileDialog, IFileOpenDialog, IFileSaveDialog, IShellItem, SHCreateItemFromParsingName, FOS_ALLOWMULTISELECT, FOS_FILEMUSTEXIST, FOS_FORCEFILESYSTEM,
46
+ FOS_OVERWRITEPROMPT, FOS_PATHMUSTEXIST, FOS_PICKFOLDERS, SIGDN_FILESYSPATH,
47
+ };
48
+ use windows::Win32::UI::WindowsAndMessaging::{
49
+ CreateWindowExW, DestroyWindow, DialogBoxIndirectParamW, EndDialog, GetClientRect, GetWindowLongPtrW, GetWindowRect, GetWindowTextLengthW, GetWindowTextW, IsWindowVisible, KillTimer, MapDialogRect,
50
+ PostMessageW, SendMessageW, SetTimer, SetWindowLongPtrW, SetWindowPos, SetWindowTextW, BS_DEFPUSHBUTTON, BS_PUSHBUTTON, DLGTEMPLATE, DM_SETDEFID, DS_MODALFRAME, DS_SETFONT,
51
+ ES_AUTOHSCROLL, GWLP_USERDATA, HMENU, HWND_MESSAGE, IDCANCEL, IDOK, SWP_NOACTIVATE, SWP_NOZORDER, WINDOW_EX_STYLE, WINDOW_STYLE, WM_COMMAND, WM_DESTROY,
52
+ WM_APP, WM_GETFONT, WM_INITDIALOG, WM_NEXTDLGCTL, WM_SETFONT, WM_TIMER, WS_CAPTION, WS_CHILD, WS_EX_CLIENTEDGE, WS_POPUP, WS_SYSMENU, WS_TABSTOP, WS_VISIBLE,
53
+ };
54
+
55
+ use crate::dialog_args::{alert_answer, mime_answer, open_answer, save_answer, strings, Alert, TestAnswers, CANCELLED};
56
+ use crate::json::{self, V};
57
+
58
+ /// Handles `panel.open`, `panel.save`, `panel.mime` and `alert.show`. false: another op (also
59
+ /// `panel.types`, macOS UTIs, which lib.rs answers UNSUPPORTED).
60
+ pub fn async_op(id: u64, json: &str, windows: &crate::Windows) -> bool {
61
+ if !json.contains("\"panel.") && !json.contains("\"alert.") {
62
+ return false;
63
+ }
64
+ let Ok(cmd) = json::parse(json) else { return false };
65
+ match cmd.get("op").and_then(|v| v.as_str()) {
66
+ Some("panel.mime") => crate::reply(id, Ok(mime_answer(&strings(cmd.get("exts")), mime_for_ext))),
67
+ // The call that showed it was cancelled or its page ended: the dialog goes. Posted to the
68
+ // dialog's own thread; its answer reaches a call nobody waits for.
69
+ Some("alert.dismiss") => {
70
+ let tag = cmd.get("tag").and_then(|v| v.as_str()).unwrap_or("");
71
+ let open = OPEN_DIALOGS.lock().unwrap().remove(tag);
72
+ if let Some((hwnd, how)) = open {
73
+ let hwnd = HWND(hwnd as *mut c_void);
74
+ let _ = match how {
75
+ Dismiss::Click(button) => unsafe { PostMessageW(Some(hwnd), TDM_CLICK_BUTTON.0 as u32, WPARAM(button as usize), LPARAM(0)) },
76
+ Dismiss::Form => unsafe { PostMessageW(Some(hwnd), WM_DISMISS, WPARAM(0), LPARAM(0)) },
77
+ };
78
+ }
79
+ crate::reply(id, Ok(format!(r#"{{"dismissed":{}}}"#, open.is_some())));
80
+ }
81
+ Some(op @ ("panel.open" | "panel.save" | "alert.show")) => {
82
+ if let Err(e) = show(id, op, &cmd, windows) {
83
+ crate::reply(id, Err(e));
84
+ }
85
+ }
86
+ _ => return false,
87
+ }
88
+ true
89
+ }
90
+
91
+ /// How `alert.dismiss` ends a dialog: a TaskDialog by clicking one of its buttons (TaskDialog has no
92
+ /// "end without an answer"), our own form by WM_DISMISS.
93
+ #[derive(Clone, Copy)]
94
+ enum Dismiss {
95
+ Click(i32),
96
+ Form,
97
+ }
98
+
99
+ /// Alerts on screen by tag: the dialog window (an isize: HWND is not Send) and how to end it.
100
+ static OPEN_DIALOGS: LazyLock<Mutex<HashMap<String, (isize, Dismiss)>>> = LazyLock::new(Default::default);
101
+
102
+ /// Ends our own form without an answer (-1).
103
+ const WM_DISMISS: u32 = WM_APP + 1;
104
+
105
+ /// What a dialog thread shows.
106
+ enum Job {
107
+ Alert { alert: Alert, caption: String },
108
+ Open { directory: bool, multiple: bool, types: Vec<String> },
109
+ Save { name: Option<String> },
110
+ }
111
+
112
+ fn show(id: u64, op: &str, cmd: &V, windows: &crate::Windows) -> Result<(), String> {
113
+ let wid = match crate::window_arg(cmd)? {
114
+ Some(w) => w,
115
+ None => windows.primary().ok_or("there is no window")?,
116
+ };
117
+ let win = windows.map.get(&wid).ok_or_else(|| format!("no window {wid}"))?;
118
+ if !win.window.is_visible() {
119
+ win.window.set_visible(true);
120
+ }
121
+ let job = match op {
122
+ "alert.show" => Job::Alert { alert: Alert::parse(cmd), caption: windows.shell.title.clone() },
123
+ "panel.save" => Job::Save { name: cmd.get("name").and_then(|v| v.as_str()).map(str::to_string) },
124
+ _ => Job::Open {
125
+ directory: cmd.get("directory").and_then(|v| v.as_bool()).unwrap_or(false),
126
+ multiple: cmd.get("multiple").and_then(|v| v.as_bool()).unwrap_or(false),
127
+ types: strings(cmd.get("types")),
128
+ },
129
+ };
130
+ let owner = win.window.hwnd(); // an isize: HWND is not Send
131
+ let test = TestAnswers::get(windows.shell.devtools);
132
+ std::thread::Builder::new()
133
+ .name("akan-native dialog".into())
134
+ .spawn(move || crate::reply(id, dialog_thread(HWND(owner as *mut c_void), test, job)))
135
+ .map(drop)
136
+ .map_err(|e| format!("INTERNAL: cannot start the dialog thread: {e}"))
137
+ }
138
+
139
+ fn dialog_thread(owner: HWND, test: Option<&'static TestAnswers>, job: Job) -> Result<String, String> {
140
+ // The file dialogs are COM objects of a single-threaded apartment.
141
+ let com = unsafe { CoInitializeEx(None, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE) };
142
+ let result = {
143
+ let controls = CommonControls::activate();
144
+ match job {
145
+ Job::Alert { alert, caption } => {
146
+ let task_dialog = controls.as_ref().and_then(|_| task_dialog_fn());
147
+ let answer = match task_dialog {
148
+ Some(f) if alert.input.is_none() => task_alert(f, owner, &caption, &alert, test),
149
+ _ => form(owner, &caption, &alert, test),
150
+ };
151
+ answer.map(|(button, text)| alert_answer(button, text.as_deref()))
152
+ }
153
+ Job::Open { directory, multiple, types } => unsafe { open(owner, directory, multiple, &types, test) },
154
+ Job::Save { name } => unsafe { save(owner, name.as_deref(), test) },
155
+ }
156
+ };
157
+ if com.is_ok() {
158
+ unsafe { CoUninitialize() };
159
+ }
160
+ result
161
+ }
162
+
163
+ fn internal(context: &str) -> impl Fn(windows::core::Error) -> String + '_ {
164
+ move |e| format!("INTERNAL: {context}: {e}")
165
+ }
166
+
167
+ // ───────────────────────── Common Controls 6 ─────────────────────────
168
+
169
+ // winbase.h; the constants live in a large windows-rs module (Win32_System_WindowsProgramming).
170
+ const ACTCTX_FLAG_RESOURCE_NAME_VALID: u32 = 0x8;
171
+ const ACTCTX_FLAG_HMODULE_VALID: u32 = 0x80;
172
+ /// ISOLATIONAWARE_MANIFEST_RESOURCE_ID: where the linker puts a DLL's manifest (build.rs).
173
+ const DLL_MANIFEST: u16 = 2;
174
+
175
+ /// This DLL: the module that holds ANCHOR, not the executable.
176
+ fn this_module() -> Option<HMODULE> {
177
+ static ANCHOR: u8 = 0;
178
+ let mut module = HMODULE::default();
179
+ let flags = GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT;
180
+ unsafe { GetModuleHandleExW(flags, PCWSTR(&ANCHOR as *const u8 as *const u16), &mut module) }.ok()?;
181
+ Some(module)
182
+ }
183
+
184
+ /// This DLL's manifest (Common Controls 6) as this thread's activation context while it lives.
185
+ struct CommonControls {
186
+ context: HANDLE,
187
+ cookie: usize,
188
+ }
189
+
190
+ impl CommonControls {
191
+ fn activate() -> Option<CommonControls> {
192
+ let module = this_module()?;
193
+ unsafe {
194
+ let request = ACTCTXW {
195
+ cbSize: size_of::<ACTCTXW>() as u32,
196
+ dwFlags: ACTCTX_FLAG_HMODULE_VALID | ACTCTX_FLAG_RESOURCE_NAME_VALID,
197
+ lpResourceName: PCWSTR(DLL_MANIFEST as usize as *const u16),
198
+ hModule: module,
199
+ ..Default::default()
200
+ };
201
+ let context = CreateActCtxW(&request).map_err(|e| log!("dialogs: no Common Controls 6 manifest in the DLL ({e}); plain controls")).ok()?;
202
+ let mut cookie = 0;
203
+ if let Err(e) = ActivateActCtx(Some(context), &mut cookie) {
204
+ log!("dialogs: cannot activate Common Controls 6 ({e})");
205
+ ReleaseActCtx(context);
206
+ return None;
207
+ }
208
+ Some(CommonControls { context, cookie })
209
+ }
210
+ }
211
+ }
212
+
213
+ impl Drop for CommonControls {
214
+ fn drop(&mut self) {
215
+ unsafe {
216
+ let _ = DeactivateActCtx(0, self.cookie);
217
+ ReleaseActCtx(self.context);
218
+ }
219
+ }
220
+ }
221
+
222
+ type TaskDialogIndirect = unsafe extern "system" fn(*const TASKDIALOGCONFIG, *mut i32, *mut i32, *mut BOOL) -> HRESULT;
223
+
224
+ /// TaskDialogIndirect of comctl32 6 (5.82, what a process without a manifest gets, has none). The
225
+ /// first call runs under CommonControls, so the loader picks version 6 from the side-by-side store.
226
+ fn task_dialog_fn() -> Option<TaskDialogIndirect> {
227
+ static FN: OnceLock<Option<usize>> = OnceLock::new();
228
+ let f = *FN.get_or_init(|| unsafe {
229
+ let comctl = LoadLibraryW(w!("comctl32.dll")).ok()?;
230
+ GetProcAddress(comctl, windows::core::s!("TaskDialogIndirect")).map(|f| f as usize)
231
+ });
232
+ // Safety: the export has this signature (commctrl.h).
233
+ f.map(|f| unsafe { std::mem::transmute::<usize, TaskDialogIndirect>(f) })
234
+ }
235
+
236
+ // ───────────────────────── alerts ─────────────────────────
237
+
238
+ /// Button ids: after IDOK..IDCONTINUE, which TaskDialog and the dialog manager use themselves.
239
+ const BUTTON_ID: i32 = 100;
240
+
241
+ /// Tests: which button the TaskDialog's timer notification clicks, once.
242
+ struct TestClick {
243
+ delay: u32,
244
+ /// A button id to click, and the answer to give when the test's button is not one of the dialog's.
245
+ click: i32,
246
+ answer: Option<isize>,
247
+ done: bool,
248
+ }
249
+
250
+ /// What the TaskDialog callback needs: the tag to file the dialog under, and the test's click.
251
+ struct TaskCallback {
252
+ tag: Option<String>,
253
+ /// The button `alert.dismiss` clicks: the cancel button, else the first.
254
+ dismiss: i32,
255
+ click: Option<TestClick>,
256
+ }
257
+
258
+ /// `alert.show` as a TaskDialog: the title is the main instruction and the message the content under
259
+ /// it (NSAlert's messageText / informativeText), the buttons in their order with the first one as
260
+ /// the default. Escape and the close button answer with the cancel button; without one the dialog
261
+ /// cannot be cancelled. No destructive style: TaskDialog has none.
262
+ fn task_alert(f: TaskDialogIndirect, owner: HWND, caption: &str, a: &Alert, test: Option<&'static TestAnswers>) -> Result<(isize, Option<String>), String> {
263
+ let (main, content) = a.lines();
264
+ let (caption, main_w, content_w) = (HSTRING::from(caption), HSTRING::from(main), HSTRING::from(content));
265
+ let labels: Vec<HSTRING> = a.buttons.iter().map(|(label, _)| HSTRING::from(label.as_str())).collect();
266
+ let buttons: Vec<TASKDIALOG_BUTTON> = labels.iter().enumerate().map(|(i, l)| TASKDIALOG_BUTTON { nButtonID: BUTTON_ID + i as i32, pszButtonText: PCWSTR(l.as_ptr()) }).collect();
267
+ let n = buttons.len() as isize;
268
+ let cancel = a.cancel();
269
+ let text = |s: &HSTRING| if s.is_empty() { PCWSTR::null() } else { PCWSTR(s.as_ptr()) };
270
+
271
+ let mut flags = TDF_POSITION_RELATIVE_TO_WINDOW | TDF_SIZE_TO_CONTENT;
272
+ if cancel.is_some() {
273
+ flags |= TDF_ALLOW_DIALOG_CANCELLATION;
274
+ }
275
+ // A packed struct (commctrl.h): fields are assigned whole, never borrowed.
276
+ let mut config = TASKDIALOGCONFIG::default();
277
+ config.cbSize = size_of::<TASKDIALOGCONFIG>() as u32;
278
+ config.hwndParent = owner;
279
+ config.pszWindowTitle = PCWSTR(caption.as_ptr());
280
+ config.pszMainInstruction = text(&main_w);
281
+ config.pszContent = text(&content_w);
282
+ config.cButtons = buttons.len() as u32;
283
+ config.pButtons = buttons.as_ptr();
284
+ config.nDefaultButton = BUTTON_ID;
285
+ let click = test.map(|t| {
286
+ let known = (0..n).contains(&t.button);
287
+ TestClick { delay: t.delay_ms(), click: BUTTON_ID + if known { t.button as i32 } else { 0 }, answer: (!known).then_some(t.button), done: false }
288
+ });
289
+ if click.is_some() {
290
+ // TDN_TIMER comes about every 200 ms with the time since the dialog was created.
291
+ flags |= TDF_CALLBACK_TIMER;
292
+ }
293
+ let mut callback = TaskCallback { tag: a.tag.clone(), dismiss: BUTTON_ID + cancel.unwrap_or(0) as i32, click };
294
+ config.pfCallback = Some(task_callback);
295
+ config.lpCallbackData = &mut callback as *mut TaskCallback as isize;
296
+ config.dwFlags = flags;
297
+ let mut pressed = 0;
298
+ let shown = unsafe { f(&config, &mut pressed, std::ptr::null_mut(), std::ptr::null_mut()) }.ok().map_err(internal("TaskDialogIndirect"));
299
+ if let Some(tag) = &callback.tag {
300
+ OPEN_DIALOGS.lock().unwrap().remove(tag);
301
+ }
302
+ shown?;
303
+ if let Some(answer) = callback.click.and_then(|c| c.answer) {
304
+ return Ok((answer, None));
305
+ }
306
+ let button = match pressed as isize - BUTTON_ID as isize {
307
+ i if (0..n).contains(&i) => i,
308
+ _ => cancel.map_or(-1, |c| c as isize), // IDCANCEL: Escape or the close button
309
+ };
310
+ Ok((button, None))
311
+ }
312
+
313
+ unsafe extern "system" fn task_callback(hwnd: HWND, msg: TASKDIALOG_NOTIFICATIONS, wparam: WPARAM, _: LPARAM, data: isize) -> HRESULT {
314
+ let callback = unsafe { &mut *(data as *mut TaskCallback) };
315
+ if msg == TDN_CREATED {
316
+ if let Some(tag) = &callback.tag {
317
+ OPEN_DIALOGS.lock().unwrap().insert(tag.clone(), (hwnd.0 as isize, Dismiss::Click(callback.dismiss)));
318
+ }
319
+ } else if msg == TDN_DESTROYED {
320
+ if let Some(tag) = &callback.tag {
321
+ OPEN_DIALOGS.lock().unwrap().remove(tag);
322
+ }
323
+ } else if msg == TDN_TIMER {
324
+ if let Some(click) = &mut callback.click {
325
+ if !click.done && wparam.0 >= click.delay as usize {
326
+ click.done = true;
327
+ unsafe { SendMessageW(hwnd, TDM_CLICK_BUTTON.0 as u32, Some(WPARAM(click.click as usize)), Some(LPARAM(0))) };
328
+ }
329
+ }
330
+ }
331
+ S_OK
332
+ }
333
+
334
+ /// Our own dialog: a prompt (a text field under the text), or an alert when there is no TaskDialog.
335
+ /// An empty in-memory template (Segoe UI 9 pt) whose controls WM_INITDIALOG creates and lays out in
336
+ /// dialog units (MapDialogRect), so the layout follows the font and the monitor's DPI. The buttons
337
+ /// are in their order, right-aligned, the first one the default (Return).
338
+ struct Form<'a> {
339
+ alert: &'a Alert,
340
+ owner: HWND,
341
+ test: Option<&'static TestAnswers>,
342
+ edit: Option<HWND>,
343
+ bold: Option<HFONT>,
344
+ done: bool,
345
+ button: isize,
346
+ text: Option<String>,
347
+ }
348
+
349
+ const TEST_TIMER: usize = 1;
350
+
351
+ fn form(owner: HWND, caption: &str, a: &Alert, test: Option<&'static TestAnswers>) -> Result<(isize, Option<String>), String> {
352
+ let mut form = Form { alert: a, owner, test, edit: None, bold: None, done: false, button: -1, text: None };
353
+ let template = template(caption, a.cancel().is_some());
354
+ let module = this_module().map(|m| HINSTANCE(m.0));
355
+ let result = unsafe { DialogBoxIndirectParamW(module, template.as_ptr() as *const DLGTEMPLATE, Some(owner), Some(form_proc), LPARAM(&mut form as *mut Form as isize)) };
356
+ if result <= 0 {
357
+ return Err(format!("INTERNAL: DialogBoxIndirectParam: {}", windows::core::Error::from_thread()));
358
+ }
359
+ Ok((form.button, form.text))
360
+ }
361
+
362
+ /// DLGTEMPLATE, no menu, the default class, the caption and DS_SETFONT's font; no items. DWORD
363
+ /// aligned, as the dialog manager requires.
364
+ fn template(caption: &str, closable: bool) -> Vec<u32> {
365
+ let style = WS_POPUP.0 | WS_CAPTION.0 | if closable { WS_SYSMENU.0 } else { 0 } | DS_MODALFRAME as u32 | DS_SETFONT as u32;
366
+ // style, extended style, item count, x, y, cx, cy (resized in WM_INITDIALOG), menu, class
367
+ let mut words: Vec<u16> = vec![style as u16, (style >> 16) as u16, 0, 0, 0, 0, 0, 200, 60, 0, 0];
368
+ words.extend(caption.encode_utf16().chain([0]));
369
+ words.push(9); // points
370
+ words.extend("Segoe UI".encode_utf16().chain([0]));
371
+ let mut out = vec![0u32; words.len().div_ceil(2)];
372
+ // Safety: `out` has room for every word.
373
+ unsafe { std::ptr::copy_nonoverlapping(words.as_ptr(), out.as_mut_ptr() as *mut u16, words.len()) };
374
+ out
375
+ }
376
+
377
+ unsafe extern "system" fn form_proc(hwnd: HWND, msg: u32, wparam: WPARAM, lparam: LPARAM) -> isize {
378
+ unsafe {
379
+ if msg == WM_INITDIALOG {
380
+ SetWindowLongPtrW(hwnd, GWLP_USERDATA, lparam.0);
381
+ let form = &mut *(lparam.0 as *mut Form);
382
+ form.layout(hwnd);
383
+ if let Some(tag) = &form.alert.tag {
384
+ OPEN_DIALOGS.lock().unwrap().insert(tag.clone(), (hwnd.0 as isize, Dismiss::Form));
385
+ }
386
+ if let Some(t) = form.test {
387
+ SetTimer(Some(hwnd), TEST_TIMER, t.delay_ms(), None);
388
+ }
389
+ // FALSE: the focus is set (the text field); TRUE: the dialog manager focuses the first button.
390
+ return form.edit.is_none() as isize;
391
+ }
392
+ let Some(form) = (GetWindowLongPtrW(hwnd, GWLP_USERDATA) as *mut Form).as_mut() else { return 0 };
393
+ match msg {
394
+ WM_COMMAND => {
395
+ let n = form.alert.buttons.len() as i32;
396
+ let button = match (wparam.0 & 0xffff) as i32 {
397
+ id if (BUTTON_ID..BUTTON_ID + n).contains(&id) => (id - BUTTON_ID) as isize,
398
+ id if id == IDOK.0 => 0, // Return
399
+ id if id == IDCANCEL.0 => match form.alert.cancel() {
400
+ Some(c) => c as isize, // Escape, the close button
401
+ None => return 1,
402
+ },
403
+ _ => return 0,
404
+ };
405
+ form.finish(hwnd, button);
406
+ 1
407
+ }
408
+ WM_TIMER if wparam.0 == TEST_TIMER => {
409
+ let _ = KillTimer(Some(hwnd), TEST_TIMER);
410
+ if let Some(t) = form.test {
411
+ if let (Some(edit), Some(text)) = (form.edit, &t.text) {
412
+ let _ = SetWindowTextW(edit, &HSTRING::from(text.as_str()));
413
+ }
414
+ form.finish(hwnd, t.button);
415
+ }
416
+ 1
417
+ }
418
+ WM_DISMISS => {
419
+ form.finish(hwnd, -1);
420
+ 1
421
+ }
422
+ WM_DESTROY => {
423
+ if let Some(bold) = form.bold.take() {
424
+ let _ = DeleteObject(bold.into());
425
+ }
426
+ if let Some(tag) = &form.alert.tag {
427
+ OPEN_DIALOGS.lock().unwrap().remove(tag);
428
+ }
429
+ 0
430
+ }
431
+ _ => 0,
432
+ }
433
+ }
434
+ }
435
+
436
+ impl Form<'_> {
437
+ unsafe fn finish(&mut self, hwnd: HWND, button: isize) {
438
+ if std::mem::replace(&mut self.done, true) {
439
+ return;
440
+ }
441
+ self.button = button;
442
+ self.text = self.edit.map(|edit| unsafe { window_text(edit) });
443
+ let _ = unsafe { EndDialog(hwnd, 1) };
444
+ }
445
+
446
+ unsafe fn layout(&mut self, hwnd: HWND) {
447
+ unsafe {
448
+ let font = HFONT(SendMessageW(hwnd, WM_GETFONT, None, None).0 as *mut c_void);
449
+ // Dialog units (a quarter of the font's average width, an eighth of its height) in pixels.
450
+ let du = |x: i32, y: i32| {
451
+ let mut r = RECT { left: 0, top: 0, right: x, bottom: y };
452
+ let _ = MapDialogRect(hwnd, &mut r);
453
+ (r.right, r.bottom)
454
+ };
455
+ let (mx, my) = du(7, 7);
456
+ let (gx, gy) = du(4, 4);
457
+ let (bw, bh) = du(50, 14);
458
+ let (pad, _) = du(10, 0);
459
+ let mut width = du(220, 0).0;
460
+
461
+ let labels: Vec<String> = self.alert.buttons.iter().map(|(l, _)| l.clone()).collect();
462
+ let widths: Vec<i32> = labels.iter().map(|l| bw.max(measure(hwnd, font, l, 0).0 + pad)).collect();
463
+ let row = widths.iter().sum::<i32>() + gx * (widths.len() as i32 - 1);
464
+ width = width.max(row);
465
+
466
+ let (primary, secondary) = self.alert.lines();
467
+ let mut y = my;
468
+ if !primary.is_empty() {
469
+ // The title in bold over the message, as NSAlert and TaskDialog set it apart.
470
+ let label_font = if secondary.is_empty() { font } else { self.bold_font(font) };
471
+ let h = measure(hwnd, label_font, primary, width).1;
472
+ control(hwnd, w!("STATIC"), primary, 0x80 /* SS_NOPREFIX */, WINDOW_EX_STYLE(0), -1, (mx, y, width, h), label_font);
473
+ y += h + gy;
474
+ }
475
+ if !secondary.is_empty() {
476
+ let h = measure(hwnd, font, secondary, width).1;
477
+ control(hwnd, w!("STATIC"), secondary, 0x80, WINDOW_EX_STYLE(0), -1, (mx, y, width, h), font);
478
+ y += h + gy;
479
+ }
480
+ if let Some((text, placeholder)) = &self.alert.input {
481
+ let edit = control(hwnd, w!("EDIT"), text, WS_TABSTOP.0 | ES_AUTOHSCROLL as u32, WS_EX_CLIENTEDGE, BUTTON_ID - 1, (mx, y, width, bh), font);
482
+ if !placeholder.is_empty() {
483
+ let cue = HSTRING::from(placeholder.as_str());
484
+ // TRUE: shown while the (focused) field is empty.
485
+ SendMessageW(edit, EM_SETCUEBANNER, Some(WPARAM(1)), Some(LPARAM(cue.as_ptr() as isize)));
486
+ }
487
+ SendMessageW(edit, EM_SETSEL, Some(WPARAM(0)), Some(LPARAM(-1)));
488
+ // The dialog manager's way to focus a control (WM_INITDIALOG then returns FALSE).
489
+ SendMessageW(hwnd, WM_NEXTDLGCTL, Some(WPARAM(edit.0 as usize)), Some(LPARAM(1)));
490
+ self.edit = Some(edit);
491
+ y += bh + gy;
492
+ }
493
+ y += my - gy;
494
+ let mut x = mx + width - row;
495
+ for (i, (label, w)) in labels.iter().zip(&widths).enumerate() {
496
+ let style = WS_TABSTOP.0 | if i == 0 { BS_DEFPUSHBUTTON } else { BS_PUSHBUTTON } as u32;
497
+ control(hwnd, w!("BUTTON"), label, style, WINDOW_EX_STYLE(0), BUTTON_ID + i as i32, (x, y, *w, bh), font);
498
+ x += w + gx;
499
+ }
500
+ SendMessageW(hwnd, DM_SETDEFID, Some(WPARAM(BUTTON_ID as usize)), None);
501
+
502
+ // Client size → window size, centered on the owner.
503
+ let (cw, ch) = (mx + width + mx, y + bh + my);
504
+ let (mut outer, mut inner, mut owner) = (RECT::default(), RECT::default(), RECT::default());
505
+ let _ = GetWindowRect(hwnd, &mut outer);
506
+ let _ = GetClientRect(hwnd, &mut inner);
507
+ let _ = GetWindowRect(self.owner, &mut owner);
508
+ let (ww, wh) = (cw + (outer.right - outer.left) - inner.right, ch + (outer.bottom - outer.top) - inner.bottom);
509
+ let (x, y) = ((owner.left + owner.right - ww) / 2, (owner.top + owner.bottom - wh) / 2);
510
+ let _ = SetWindowPos(hwnd, None, x, y, ww, wh, SWP_NOZORDER | SWP_NOACTIVATE);
511
+ }
512
+ }
513
+
514
+ /// The dialog font in bold, deleted with the dialog.
515
+ unsafe fn bold_font(&mut self, font: HFONT) -> HFONT {
516
+ unsafe {
517
+ let mut lf = LOGFONTW::default();
518
+ if GetObjectW(font.into(), size_of::<LOGFONTW>() as i32, Some(&mut lf as *mut LOGFONTW as *mut c_void)) == 0 {
519
+ return font;
520
+ }
521
+ lf.lfWeight = FW_BOLD.0 as i32;
522
+ let bold = CreateFontIndirectW(&lf);
523
+ if bold.is_invalid() {
524
+ return font;
525
+ }
526
+ self.bold = Some(bold);
527
+ bold
528
+ }
529
+ }
530
+ }
531
+
532
+ /// A child control with the dialog's font.
533
+ unsafe fn control(parent: HWND, class: PCWSTR, text: &str, style: u32, ex: WINDOW_EX_STYLE, id: i32, (x, y, w, h): (i32, i32, i32, i32), font: HFONT) -> HWND {
534
+ unsafe {
535
+ let menu = HMENU(id as isize as *mut c_void); // a child's id
536
+ let child = CreateWindowExW(ex, class, &HSTRING::from(text), WINDOW_STYLE(WS_CHILD.0 | WS_VISIBLE.0 | style), x, y, w, h, Some(parent), Some(menu), None, None).unwrap_or_default();
537
+ SendMessageW(child, WM_SETFONT, Some(WPARAM(font.0 as usize)), Some(LPARAM(1)));
538
+ child
539
+ }
540
+ }
541
+
542
+ /// The size of `text` in `font`: one line when `width` is 0, else wrapped to `width`.
543
+ unsafe fn measure(hwnd: HWND, font: HFONT, text: &str, width: i32) -> (i32, i32) {
544
+ unsafe {
545
+ let dc = GetDC(Some(hwnd));
546
+ let old = SelectObject(dc, font.into());
547
+ let mut wide: Vec<u16> = text.encode_utf16().collect();
548
+ let mut r = RECT { left: 0, top: 0, right: width, bottom: 0 };
549
+ let format: DRAW_TEXT_FORMAT = DT_CALCRECT | DT_NOPREFIX | DT_EXPANDTABS | if width == 0 { DT_SINGLELINE } else { DT_WORDBREAK };
550
+ DrawTextW(dc, &mut wide, &mut r, format);
551
+ SelectObject(dc, old);
552
+ ReleaseDC(Some(hwnd), dc);
553
+ (r.right - r.left, r.bottom - r.top)
554
+ }
555
+ }
556
+
557
+ unsafe fn window_text(hwnd: HWND) -> String {
558
+ unsafe {
559
+ let mut buf = vec![0u16; GetWindowTextLengthW(hwnd) as usize + 1];
560
+ let n = GetWindowTextW(hwnd, &mut buf);
561
+ String::from_utf16_lossy(&buf[..n.max(0) as usize])
562
+ }
563
+ }
564
+
565
+ // ───────────────────────── file dialogs ─────────────────────────
566
+
567
+ const CANCELLED_HR: HRESULT = HRESULT::from_win32(ERROR_CANCELLED.0);
568
+
569
+ unsafe fn open(owner: HWND, directory: bool, multiple: bool, types: &[String], test: Option<&'static TestAnswers>) -> Result<String, String> {
570
+ unsafe {
571
+ let dialog: IFileOpenDialog = CoCreateInstance(&FileOpenDialog, None, CLSCTX_INPROC_SERVER).map_err(internal("FileOpenDialog"))?;
572
+ let mut options = dialog.GetOptions().map_err(internal("GetOptions"))? | FOS_FORCEFILESYSTEM | FOS_PATHMUSTEXIST | FOS_FILEMUSTEXIST;
573
+ if directory {
574
+ options |= FOS_PICKFOLDERS;
575
+ } else if multiple {
576
+ options |= FOS_ALLOWMULTISELECT;
577
+ }
578
+ dialog.SetOptions(options).map_err(internal("SetOptions"))?;
579
+ // Kept alive until Show returns: the dialog holds the pointers.
580
+ let spec = (!directory).then(|| filter(types)).flatten().map(|s| HSTRING::from(s.as_str()));
581
+ if let Some(spec) = &spec {
582
+ dialog.SetFileTypes(&[COMDLG_FILTERSPEC { pszName: PCWSTR(spec.as_ptr()), pszSpec: PCWSTR(spec.as_ptr()) }]).map_err(internal("SetFileTypes"))?;
583
+ }
584
+ prepare(&dialog, test, None);
585
+ match show_modal(&dialog, owner, test, directory) {
586
+ Err(e) if e.code() == CANCELLED_HR => return Ok(CANCELLED.into()),
587
+ Err(e) => return Err(internal("Show")(e)),
588
+ Ok(()) => {}
589
+ }
590
+ let items = dialog.GetResults().map_err(internal("GetResults"))?;
591
+ let mut paths = Vec::new();
592
+ for i in 0..items.GetCount().map_err(internal("GetCount"))? {
593
+ paths.push(path_of(&items.GetItemAt(i).map_err(internal("GetItemAt"))?)?);
594
+ }
595
+ Ok(open_answer(&paths))
596
+ }
597
+ }
598
+
599
+ unsafe fn save(owner: HWND, name: Option<&str>, test: Option<&'static TestAnswers>) -> Result<String, String> {
600
+ unsafe {
601
+ let dialog: IFileSaveDialog = CoCreateInstance(&FileSaveDialog, None, CLSCTX_INPROC_SERVER).map_err(internal("FileSaveDialog"))?;
602
+ // The plugin writes the file without asking again, as after NSSavePanel.
603
+ let options = dialog.GetOptions().map_err(internal("GetOptions"))? | FOS_FORCEFILESYSTEM | FOS_PATHMUSTEXIST | FOS_OVERWRITEPROMPT;
604
+ dialog.SetOptions(options).map_err(internal("SetOptions"))?;
605
+ if let Some(name) = name {
606
+ let _ = dialog.SetFileName(&HSTRING::from(name));
607
+ // A name typed without an extension gets the suggested one.
608
+ if let Some((_, ext)) = name.rsplit_once('.').filter(|(stem, ext)| !stem.is_empty() && !ext.is_empty()) {
609
+ let _ = dialog.SetDefaultExtension(&HSTRING::from(ext));
610
+ }
611
+ }
612
+ prepare(&dialog, test, name);
613
+ match show_modal(&dialog, owner, test, true) {
614
+ Err(e) if e.code() == CANCELLED_HR => return Ok(CANCELLED.into()),
615
+ Err(e) => return Err(internal("Show")(e)),
616
+ Ok(()) => {}
617
+ }
618
+ let item = dialog.GetResult().map_err(internal("GetResult"))?;
619
+ Ok(save_answer(Some(&path_of(&item)?)))
620
+ }
621
+ }
622
+
623
+ unsafe fn path_of(item: &IShellItem) -> Result<String, String> {
624
+ unsafe {
625
+ let path: PWSTR = item.GetDisplayName(SIGDN_FILESYSPATH).map_err(internal("GetDisplayName"))?;
626
+ let s = path.to_string().map_err(|e| format!("INTERNAL: a path is not UTF-16: {e}"));
627
+ CoTaskMemFree(Some(path.0 as *const c_void));
628
+ s
629
+ }
630
+ }
631
+
632
+ /// Tests: the answer's folder and name, set before the dialog is shown (as on macOS).
633
+ unsafe fn prepare(dialog: &IFileDialog, test: Option<&'static TestAnswers>, name: Option<&str>) {
634
+ let Some(t) = test else { return };
635
+ unsafe {
636
+ if let Some(dir) = &t.directory {
637
+ if let Ok(folder) = SHCreateItemFromParsingName::<_, _, IShellItem>(&HSTRING::from(dir.as_str()), None) {
638
+ let _ = dialog.SetFolder(&folder);
639
+ }
640
+ }
641
+ if let (Some(test_name), Some(_)) = (&t.name, name) {
642
+ let _ = dialog.SetFileName(&HSTRING::from(test_name.as_str()));
643
+ }
644
+ }
645
+ }
646
+
647
+ thread_local! {
648
+ /// Tests: the file dialog this thread shows, and whether to answer it with OK.
649
+ static SHOWN: RefCell<Option<(IFileDialog, bool)>> = const { RefCell::new(None) };
650
+ }
651
+
652
+ /// Shows the dialog on its owner. Tests: a timer on a message-only window of this thread ends it
653
+ /// from inside the dialog's modal loop, which dispatches this thread's messages.
654
+ unsafe fn show_modal(dialog: &IFileDialog, owner: HWND, test: Option<&'static TestAnswers>, can_ok: bool) -> windows::core::Result<()> {
655
+ unsafe {
656
+ let timer = test.and_then(|t| {
657
+ let window = CreateWindowExW(WINDOW_EX_STYLE(0), w!("STATIC"), None, WINDOW_STYLE(0), 0, 0, 0, 0, Some(HWND_MESSAGE), None, None, None).ok()?;
658
+ SHOWN.with(|s| *s.borrow_mut() = Some((dialog.clone(), t.panel_ok && can_ok)));
659
+ SetTimer(Some(window), TEST_TIMER, t.delay_ms(), Some(end_file_dialog));
660
+ Some(window)
661
+ });
662
+ let result = dialog.Show(Some(owner));
663
+ if let Some(window) = timer {
664
+ SHOWN.with(|s| s.borrow_mut().take());
665
+ let _ = DestroyWindow(window); // and its timer
666
+ }
667
+ result
668
+ }
669
+ }
670
+
671
+ /// Clicks OK or Cancel, at every tick until Show returns: Show pumps this thread's messages while it
672
+ /// builds the dialog, so a tick can come before the dialog takes clicks. IFileDialog::Close returns
673
+ /// S_OK from here but leaves the dialog open (it works from the dialog's own event callbacks).
674
+ unsafe extern "system" fn end_file_dialog(_: HWND, _: u32, _: usize, _: u32) {
675
+ unsafe {
676
+ let Some((dialog, ok)) = SHOWN.with(|s| s.borrow().clone()) else { return };
677
+ let Ok(hwnd) = dialog.cast::<IOleWindow>().and_then(|w| w.GetWindow()) else { return };
678
+ if IsWindowVisible(hwnd).as_bool() {
679
+ // OK: the folder and name prepare() set. Cancel: Show returns ERROR_CANCELLED.
680
+ let button = if ok { IDOK } else { IDCANCEL };
681
+ let _ = PostMessageW(Some(hwnd), WM_COMMAND, WPARAM(button.0 as usize), LPARAM(0));
682
+ }
683
+ }
684
+ }
685
+
686
+ // ───────────────────────── types ─────────────────────────
687
+
688
+ /// Common types the registry's MIME database often lacks (it lists what installed apps registered).
689
+ const COMMON: &[(&str, &[&str])] = &[
690
+ ("image/png", &["png"]),
691
+ ("image/jpeg", &["jpg", "jpeg", "jpe", "jfif"]),
692
+ ("image/gif", &["gif"]),
693
+ ("image/webp", &["webp"]),
694
+ ("image/bmp", &["bmp"]),
695
+ ("image/tiff", &["tif", "tiff"]),
696
+ ("image/svg+xml", &["svg"]),
697
+ ("image/heic", &["heic"]),
698
+ ("image/avif", &["avif"]),
699
+ ("image/x-icon", &["ico"]),
700
+ ("video/mp4", &["mp4", "m4v"]),
701
+ ("video/quicktime", &["mov"]),
702
+ ("video/webm", &["webm"]),
703
+ ("video/x-msvideo", &["avi"]),
704
+ ("video/x-matroska", &["mkv"]),
705
+ ("video/mpeg", &["mpeg", "mpg"]),
706
+ ("audio/mpeg", &["mp3"]),
707
+ ("audio/mp4", &["m4a"]),
708
+ ("audio/wav", &["wav"]),
709
+ ("audio/ogg", &["ogg", "oga"]),
710
+ ("audio/flac", &["flac"]),
711
+ ("audio/aac", &["aac"]),
712
+ ("text/plain", &["txt"]),
713
+ ("text/csv", &["csv"]),
714
+ ("text/html", &["html", "htm"]),
715
+ ("text/markdown", &["md", "markdown"]),
716
+ ("text/css", &["css"]),
717
+ ("text/javascript", &["js", "mjs"]),
718
+ ("application/json", &["json"]),
719
+ ("application/pdf", &["pdf"]),
720
+ ("application/zip", &["zip"]),
721
+ ("application/xml", &["xml"]),
722
+ ("application/rtf", &["rtf"]),
723
+ ("application/msword", &["doc"]),
724
+ ("application/vnd.openxmlformats-officedocument.wordprocessingml.document", &["docx"]),
725
+ ("application/vnd.ms-excel", &["xls"]),
726
+ ("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", &["xlsx"]),
727
+ ("application/vnd.ms-powerpoint", &["ppt"]),
728
+ ("application/vnd.openxmlformats-officedocument.presentationml.presentation", &["pptx"]),
729
+ ("font/ttf", &["ttf"]),
730
+ ("font/otf", &["otf"]),
731
+ ("font/woff", &["woff"]),
732
+ ("font/woff2", &["woff2"]),
733
+ ];
734
+
735
+ const MIME_DATABASE: &str = "MIME\\Database\\Content Type";
736
+
737
+ /// The filter's pattern list ("*.pdf;*.txt"), or None (every file) when a type is "*/*" or has no
738
+ /// extension this machine knows.
739
+ fn filter(types: &[String]) -> Option<String> {
740
+ filter_with(types, registry_extensions)
741
+ }
742
+
743
+ fn filter_with(types: &[String], registry: impl Fn(&str) -> Vec<String>) -> Option<String> {
744
+ if types.is_empty() {
745
+ return None;
746
+ }
747
+ let mut patterns: Vec<String> = Vec::new();
748
+ for ty in types {
749
+ if ty == "*/*" {
750
+ return None;
751
+ }
752
+ let exts = if ty.contains('/') { extensions_for_mime(ty, &registry) } else { vec![ty.trim_start_matches('.').to_ascii_lowercase()] };
753
+ if exts.is_empty() {
754
+ return None;
755
+ }
756
+ for ext in exts {
757
+ let pattern = format!("*.{ext}");
758
+ if !patterns.contains(&pattern) {
759
+ patterns.push(pattern);
760
+ }
761
+ }
762
+ }
763
+ Some(patterns.join(";"))
764
+ }
765
+
766
+ /// Extensions of a MIME type ("image/png") or a family ("image/*"): the table, then the registry.
767
+ fn extensions_for_mime(mime: &str, registry: &impl Fn(&str) -> Vec<String>) -> Vec<String> {
768
+ let mime = mime.to_ascii_lowercase();
769
+ let family = mime.strip_suffix('*');
770
+ let matches = |m: &str| family.map_or(m == mime, |prefix| m.starts_with(prefix));
771
+ let mut out: Vec<String> = Vec::new();
772
+ for ext in COMMON.iter().filter(|(m, _)| matches(m)).flat_map(|(_, exts)| exts.iter().map(|e| e.to_string())).chain(registry(&mime)) {
773
+ if !out.contains(&ext) {
774
+ out.push(ext);
775
+ }
776
+ }
777
+ out
778
+ }
779
+
780
+ /// HKCR\MIME\Database\Content Type\<type>\Extension, for one type or every type of a family.
781
+ fn registry_extensions(mime: &str) -> Vec<String> {
782
+ let ext = |ty: &str| reg_string(&format!("{MIME_DATABASE}\\{ty}"), "Extension").map(|e| e.trim_start_matches('.').to_ascii_lowercase());
783
+ match mime.strip_suffix('*') {
784
+ Some(prefix) => reg_subkeys(MIME_DATABASE).iter().filter(|t| t.to_ascii_lowercase().starts_with(prefix)).filter_map(|t| ext(t)).collect(),
785
+ None => ext(mime).into_iter().collect(),
786
+ }
787
+ }
788
+
789
+ /// The MIME type of a file extension: HKCR\.<ext>\Content Type, else the table.
790
+ fn mime_for_ext(ext: &str) -> Option<String> {
791
+ let ext = ext.trim_start_matches('.').to_ascii_lowercase();
792
+ reg_string(&format!(".{ext}"), "Content Type").or_else(|| COMMON.iter().find(|(_, exts)| exts.contains(&ext.as_str())).map(|(m, _)| m.to_string()))
793
+ }
794
+
795
+ fn reg_string(key: &str, value: &str) -> Option<String> {
796
+ super::registry::read_string(HKEY_CLASSES_ROOT, key, value).ok().flatten().filter(|s| !s.is_empty())
797
+ }
798
+
799
+ fn reg_subkeys(key: &str) -> Vec<String> {
800
+ let mut out = Vec::new();
801
+ unsafe {
802
+ let mut hkey = HKEY::default();
803
+ if RegOpenKeyExW(HKEY_CLASSES_ROOT, &HSTRING::from(key), None, KEY_READ, &mut hkey).is_err() {
804
+ return out;
805
+ }
806
+ let mut buf = [0u16; 256];
807
+ for i in 0.. {
808
+ let mut len = buf.len() as u32;
809
+ if RegEnumKeyExW(hkey, i, Some(PWSTR(buf.as_mut_ptr())), &mut len, None, None, None, None).is_err() {
810
+ break;
811
+ }
812
+ out.push(String::from_utf16_lossy(&buf[..len as usize]));
813
+ }
814
+ let _ = RegCloseKey(hkey);
815
+ }
816
+ out
817
+ }
818
+
819
+ // ───────────────────────── D7 ─────────────────────────
820
+
821
+ /// D7 under tests: WebView2 shows its own JavaScript alert/confirm/prompt dialogs, which wait for a
822
+ /// click. With AKAN_NATIVE_TEST_PANELS (dev builds) the default dialogs are turned off and the
823
+ /// ScriptDialogOpening event answers them instead: the handler takes a deferral, sets the answer and
824
+ /// completes it after the delay; the page's script waits meanwhile, as behind a real dialog. Set
825
+ /// right after the webview is built, before its first navigation starts (settings changed later
826
+ /// apply from the next navigation). Without the variable WebView2's own dialogs stay.
827
+ pub fn install_js_dialogs(dev: bool, webview: &wry::WebView) {
828
+ use webview2_com::Microsoft::Web::WebView2::Win32::{COREWEBVIEW2_SCRIPT_DIALOG_KIND, COREWEBVIEW2_SCRIPT_DIALOG_KIND_ALERT, COREWEBVIEW2_SCRIPT_DIALOG_KIND_PROMPT};
829
+ use webview2_com::ScriptDialogOpeningEventHandler;
830
+ use wry::WebViewExtWindows;
831
+ let Some(t) = TestAnswers::get(dev) else { return };
832
+ let core = webview.webview();
833
+ let handler = ScriptDialogOpeningEventHandler::create(Box::new(move |_, args| {
834
+ let Some(args) = args else { return Ok(()) };
835
+ unsafe {
836
+ let mut kind = COREWEBVIEW2_SCRIPT_DIALOG_KIND::default();
837
+ args.Kind(&mut kind)?;
838
+ let accept = t.button == 0 && kind != COREWEBVIEW2_SCRIPT_DIALOG_KIND_ALERT;
839
+ // As on macOS, a prompt keeps its default text.
840
+ if accept && kind == COREWEBVIEW2_SCRIPT_DIALOG_KIND_PROMPT {
841
+ let text = match &t.text {
842
+ Some(text) => text.clone(),
843
+ None => {
844
+ let mut default = PWSTR::null();
845
+ args.DefaultText(&mut default)?;
846
+ webview2_com::take_pwstr(default)
847
+ }
848
+ };
849
+ args.SetResultText(&HSTRING::from(text))?;
850
+ }
851
+ let deferral = args.GetDeferral()?;
852
+ later(t.delay_ms(), move || {
853
+ if accept {
854
+ let _ = args.Accept();
855
+ }
856
+ let _ = deferral.Complete();
857
+ });
858
+ }
859
+ Ok(())
860
+ }));
861
+ let result = unsafe {
862
+ let mut token = 0;
863
+ core.add_ScriptDialogOpening(&handler, &mut token).and_then(|()| core.Settings()).and_then(|s| s.SetAreDefaultScriptDialogsEnabled(false))
864
+ };
865
+ if let Err(e) = result {
866
+ log!("D7: cannot answer JavaScript dialogs in tests: {e}");
867
+ }
868
+ }
869
+
870
+ thread_local! {
871
+ /// Main-thread timers: id → what runs when it fires.
872
+ static LATER: RefCell<HashMap<usize, Box<dyn FnOnce()>>> = RefCell::new(HashMap::new());
873
+ }
874
+
875
+ /// Runs `f` on this (the main) thread after `ms`: a thread timer, dispatched by tao's message loop.
876
+ fn later(ms: u32, f: impl FnOnce() + 'static) {
877
+ let id = unsafe { SetTimer(None, 0, ms, Some(run_later)) };
878
+ if id == 0 {
879
+ return f();
880
+ }
881
+ LATER.with(|l| l.borrow_mut().insert(id, Box::new(f)));
882
+ }
883
+
884
+ unsafe extern "system" fn run_later(_: HWND, _: u32, id: usize, _: u32) {
885
+ let _ = unsafe { KillTimer(None, id) };
886
+ if let Some(f) = LATER.with(|l| l.borrow_mut().remove(&id)) {
887
+ f();
888
+ }
889
+ }
890
+
891
+ #[cfg(test)]
892
+ mod tests {
893
+ use super::*;
894
+
895
+ #[test]
896
+ fn filters() {
897
+ let none = |_: &str| Vec::new();
898
+ let types = |t: &[&str]| t.iter().map(|s| s.to_string()).collect::<Vec<_>>();
899
+ assert_eq!(filter_with(&types(&["pdf", ".TXT", "image/png"]), none).as_deref(), Some("*.pdf;*.txt;*.png"));
900
+ assert_eq!(filter_with(&types(&["audio/*"]), none).unwrap().split(';').count(), 7);
901
+ assert_eq!(filter_with(&types(&["application/x-nope"]), none), None); // unknown: no filter
902
+ assert_eq!(filter_with(&types(&["application/x-nope"]), |_| vec!["nope".into()]).as_deref(), Some("*.nope"));
903
+ assert_eq!(filter_with(&types(&["pdf", "*/*"]), none), None);
904
+ assert_eq!(filter_with(&[], none), None);
905
+ }
906
+
907
+ #[test]
908
+ fn dialog_template_is_dword_aligned_words() {
909
+ let t = template("A", true);
910
+ let words: Vec<u16> = t.iter().flat_map(|d| [*d as u16, (*d >> 16) as u16]).collect();
911
+ // style, ex style, cdit, x, y, cx, cy, menu, class, "A\0", 9, "Segoe UI\0"
912
+ assert_eq!(&words[9..13], &[0, 0, 'A' as u16, 0]);
913
+ assert_eq!(words[13], 9);
914
+ assert_eq!(String::from_utf16_lossy(&words[14..22]), "Segoe UI");
915
+ assert_eq!(words[22], 0);
916
+ }
917
+ }