@zappdev/cli 0.1.0

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 (209) hide show
  1. package/README.md +55 -0
  2. package/dist/zapp-cli.js +9471 -0
  3. package/native/src/app/app.zc +490 -0
  4. package/native/src/event/event.zc +24 -0
  5. package/native/src/event/events.zc +70 -0
  6. package/native/src/platform/darwin/backend.zc +923 -0
  7. package/native/src/platform/darwin/backend_bootstrap.zc +9 -0
  8. package/native/src/platform/darwin/bootstrap.zc +9 -0
  9. package/native/src/platform/darwin/engine_jsc.zc +86 -0
  10. package/native/src/platform/darwin/engine_qjs.zc +92 -0
  11. package/native/src/platform/darwin/platform.zc +156 -0
  12. package/native/src/platform/darwin/webview.zc +550 -0
  13. package/native/src/platform/darwin/webview_bootstrap.zc +9 -0
  14. package/native/src/platform/darwin/window.zc +1223 -0
  15. package/native/src/platform/darwin/worker/common.zc +223 -0
  16. package/native/src/platform/darwin/worker/core/base64_core.zc +29 -0
  17. package/native/src/platform/darwin/worker/core/crypto_core.zc +19 -0
  18. package/native/src/platform/darwin/worker/core/encoding_core.zc +32 -0
  19. package/native/src/platform/darwin/worker/core/fetch_core.zc +145 -0
  20. package/native/src/platform/darwin/worker/core/url_core.zc +69 -0
  21. package/native/src/platform/darwin/worker/core/websocket_core.zc +179 -0
  22. package/native/src/platform/darwin/worker/dispatch.zc +55 -0
  23. package/native/src/platform/darwin/worker/jsc/base64_jsc.zc +39 -0
  24. package/native/src/platform/darwin/worker/jsc/crypto_jsc.zc +49 -0
  25. package/native/src/platform/darwin/worker/jsc/encoding_jsc.zc +86 -0
  26. package/native/src/platform/darwin/worker/jsc/fetch_jsc.zc +149 -0
  27. package/native/src/platform/darwin/worker/jsc/url_jsc.zc +54 -0
  28. package/native/src/platform/darwin/worker/jsc/websocket_jsc.zc +127 -0
  29. package/native/src/platform/darwin/worker/jsc.zc +670 -0
  30. package/native/src/platform/darwin/worker/mod.zc +30 -0
  31. package/native/src/platform/darwin/worker/qjs/fetch_qjs.zc +233 -0
  32. package/native/src/platform/darwin/worker/qjs/qjs_macros.zc +23 -0
  33. package/native/src/platform/darwin/worker/qjs/websocket_qjs.zc +223 -0
  34. package/native/src/platform/darwin/worker/qjs.zc +1053 -0
  35. package/native/src/platform/darwin/worker/timers.zc +149 -0
  36. package/native/src/platform/darwin/worker/timers_qjs.zc +209 -0
  37. package/native/src/platform/platform.zc +64 -0
  38. package/native/src/platform/shared/log.zc +156 -0
  39. package/native/src/platform/shared/worker/qjs/base64_qjs.zc +38 -0
  40. package/native/src/platform/shared/worker/qjs/crypto_qjs.zc +44 -0
  41. package/native/src/platform/shared/worker/qjs/encoding_qjs.zc +95 -0
  42. package/native/src/platform/shared/worker/qjs/url_qjs.zc +65 -0
  43. package/native/src/platform/shared/worker_registry.zc +206 -0
  44. package/native/src/platform/window.zc +446 -0
  45. package/native/src/platform/windows/backend.zc +452 -0
  46. package/native/src/platform/windows/backend_bootstrap.zc +9 -0
  47. package/native/src/platform/windows/bootstrap.zc +9 -0
  48. package/native/src/platform/windows/engine_qjs.zc +60 -0
  49. package/native/src/platform/windows/platform.zc +387 -0
  50. package/native/src/platform/windows/webview.zc +1175 -0
  51. package/native/src/platform/windows/webview_bootstrap.zc +9 -0
  52. package/native/src/platform/windows/window.zc +1271 -0
  53. package/native/src/platform/windows/worker/common.zc +409 -0
  54. package/native/src/platform/windows/worker/core/base64_core.zc +52 -0
  55. package/native/src/platform/windows/worker/core/crypto_core.zc +34 -0
  56. package/native/src/platform/windows/worker/core/encoding_core.zc +60 -0
  57. package/native/src/platform/windows/worker/core/fetch_core.zc +274 -0
  58. package/native/src/platform/windows/worker/core/url_core.zc +216 -0
  59. package/native/src/platform/windows/worker/core/websocket_core.zc +343 -0
  60. package/native/src/platform/windows/worker/dispatch.zc +34 -0
  61. package/native/src/platform/windows/worker/mod.zc +46 -0
  62. package/native/src/platform/windows/worker/qjs/fetch_qjs.zc +255 -0
  63. package/native/src/platform/windows/worker/qjs/websocket_qjs.zc +263 -0
  64. package/native/src/platform/windows/worker/qjs.zc +1049 -0
  65. package/native/src/platform/windows/worker/timers_qjs.zc +288 -0
  66. package/native/src/platform/worker.zc +8 -0
  67. package/native/src/service/service.zc +228 -0
  68. package/native/vendor/quickjs-ng/.gitattributes +4 -0
  69. package/native/vendor/quickjs-ng/.github/dependabot.yml +7 -0
  70. package/native/vendor/quickjs-ng/.github/workflows/ci.yml +812 -0
  71. package/native/vendor/quickjs-ng/.github/workflows/docs.yml +49 -0
  72. package/native/vendor/quickjs-ng/.github/workflows/release.yml +162 -0
  73. package/native/vendor/quickjs-ng/.github/workflows/test-docs.yml +23 -0
  74. package/native/vendor/quickjs-ng/.github/workflows/tsan.yml +32 -0
  75. package/native/vendor/quickjs-ng/.github/workflows/valgrind.yml +33 -0
  76. package/native/vendor/quickjs-ng/.gitmodules +5 -0
  77. package/native/vendor/quickjs-ng/CMakeLists.txt +553 -0
  78. package/native/vendor/quickjs-ng/LICENSE +24 -0
  79. package/native/vendor/quickjs-ng/Makefile +149 -0
  80. package/native/vendor/quickjs-ng/amalgam.js +53 -0
  81. package/native/vendor/quickjs-ng/api-test.c +927 -0
  82. package/native/vendor/quickjs-ng/builtin-array-fromasync.h +119 -0
  83. package/native/vendor/quickjs-ng/builtin-array-fromasync.js +36 -0
  84. package/native/vendor/quickjs-ng/builtin-iterator-zip-keyed.h +332 -0
  85. package/native/vendor/quickjs-ng/builtin-iterator-zip-keyed.js +194 -0
  86. package/native/vendor/quickjs-ng/builtin-iterator-zip.h +337 -0
  87. package/native/vendor/quickjs-ng/builtin-iterator-zip.js +210 -0
  88. package/native/vendor/quickjs-ng/ctest.c +17 -0
  89. package/native/vendor/quickjs-ng/cutils.h +2013 -0
  90. package/native/vendor/quickjs-ng/cxxtest.cc +2 -0
  91. package/native/vendor/quickjs-ng/dtoa.c +1619 -0
  92. package/native/vendor/quickjs-ng/dtoa.h +87 -0
  93. package/native/vendor/quickjs-ng/examples/fib.c +67 -0
  94. package/native/vendor/quickjs-ng/examples/fib_module.js +10 -0
  95. package/native/vendor/quickjs-ng/examples/hello.js +1 -0
  96. package/native/vendor/quickjs-ng/examples/hello_module.js +6 -0
  97. package/native/vendor/quickjs-ng/examples/meson.build +17 -0
  98. package/native/vendor/quickjs-ng/examples/pi_bigint.js +118 -0
  99. package/native/vendor/quickjs-ng/examples/point.c +154 -0
  100. package/native/vendor/quickjs-ng/examples/test_fib.js +8 -0
  101. package/native/vendor/quickjs-ng/examples/test_point.js +43 -0
  102. package/native/vendor/quickjs-ng/fuzz.c +51 -0
  103. package/native/vendor/quickjs-ng/gen/function_source.c +81 -0
  104. package/native/vendor/quickjs-ng/gen/hello.c +53 -0
  105. package/native/vendor/quickjs-ng/gen/hello_module.c +106 -0
  106. package/native/vendor/quickjs-ng/gen/repl.c +3053 -0
  107. package/native/vendor/quickjs-ng/gen/standalone.c +324 -0
  108. package/native/vendor/quickjs-ng/gen/test_fib.c +81 -0
  109. package/native/vendor/quickjs-ng/libregexp-opcode.h +58 -0
  110. package/native/vendor/quickjs-ng/libregexp.c +2687 -0
  111. package/native/vendor/quickjs-ng/libregexp.h +98 -0
  112. package/native/vendor/quickjs-ng/libunicode-table.h +4707 -0
  113. package/native/vendor/quickjs-ng/libunicode.c +1746 -0
  114. package/native/vendor/quickjs-ng/libunicode.h +126 -0
  115. package/native/vendor/quickjs-ng/list.h +107 -0
  116. package/native/vendor/quickjs-ng/lre-test.c +73 -0
  117. package/native/vendor/quickjs-ng/meson.build +684 -0
  118. package/native/vendor/quickjs-ng/meson_options.txt +6 -0
  119. package/native/vendor/quickjs-ng/qjs-wasi-reactor.c +208 -0
  120. package/native/vendor/quickjs-ng/qjs.c +748 -0
  121. package/native/vendor/quickjs-ng/qjsc.c +673 -0
  122. package/native/vendor/quickjs-ng/quickjs-atom.h +267 -0
  123. package/native/vendor/quickjs-ng/quickjs-c-atomics.h +54 -0
  124. package/native/vendor/quickjs-ng/quickjs-libc.c +4986 -0
  125. package/native/vendor/quickjs-ng/quickjs-libc.h +79 -0
  126. package/native/vendor/quickjs-ng/quickjs-opcode.h +369 -0
  127. package/native/vendor/quickjs-ng/quickjs.c +60259 -0
  128. package/native/vendor/quickjs-ng/quickjs.h +1419 -0
  129. package/native/vendor/quickjs-ng/repl.js +1927 -0
  130. package/native/vendor/quickjs-ng/run-test262.c +2417 -0
  131. package/native/vendor/quickjs-ng/standalone.js +129 -0
  132. package/native/vendor/quickjs-ng/tests/assert.js +49 -0
  133. package/native/vendor/quickjs-ng/tests/bug1221.js +16 -0
  134. package/native/vendor/quickjs-ng/tests/bug1296.js +12 -0
  135. package/native/vendor/quickjs-ng/tests/bug1297.js +22 -0
  136. package/native/vendor/quickjs-ng/tests/bug1301.js +21 -0
  137. package/native/vendor/quickjs-ng/tests/bug1302.js +24 -0
  138. package/native/vendor/quickjs-ng/tests/bug1305.js +26 -0
  139. package/native/vendor/quickjs-ng/tests/bug1318.js +54 -0
  140. package/native/vendor/quickjs-ng/tests/bug1352.js +8 -0
  141. package/native/vendor/quickjs-ng/tests/bug1354.js +6 -0
  142. package/native/vendor/quickjs-ng/tests/bug1355.js +58 -0
  143. package/native/vendor/quickjs-ng/tests/bug1368.js +9 -0
  144. package/native/vendor/quickjs-ng/tests/bug39/1.js +6 -0
  145. package/native/vendor/quickjs-ng/tests/bug39/2.js +6 -0
  146. package/native/vendor/quickjs-ng/tests/bug39/3.js +7 -0
  147. package/native/vendor/quickjs-ng/tests/bug488-upstream.js +7 -0
  148. package/native/vendor/quickjs-ng/tests/bug633/0.js +7 -0
  149. package/native/vendor/quickjs-ng/tests/bug633/1.js +4 -0
  150. package/native/vendor/quickjs-ng/tests/bug633/2.js +4 -0
  151. package/native/vendor/quickjs-ng/tests/bug633/3.js +4 -0
  152. package/native/vendor/quickjs-ng/tests/bug645/0.js +4 -0
  153. package/native/vendor/quickjs-ng/tests/bug645/1.js +9 -0
  154. package/native/vendor/quickjs-ng/tests/bug645/2.js +7 -0
  155. package/native/vendor/quickjs-ng/tests/bug648.js +13 -0
  156. package/native/vendor/quickjs-ng/tests/bug652.js +4 -0
  157. package/native/vendor/quickjs-ng/tests/bug741.js +19 -0
  158. package/native/vendor/quickjs-ng/tests/bug775.js +7 -0
  159. package/native/vendor/quickjs-ng/tests/bug776.js +7 -0
  160. package/native/vendor/quickjs-ng/tests/bug832.js +2 -0
  161. package/native/vendor/quickjs-ng/tests/bug858.js +26 -0
  162. package/native/vendor/quickjs-ng/tests/bug904.js +6 -0
  163. package/native/vendor/quickjs-ng/tests/bug988.js +7 -0
  164. package/native/vendor/quickjs-ng/tests/bug999.js +3 -0
  165. package/native/vendor/quickjs-ng/tests/destructured-export.js +8 -0
  166. package/native/vendor/quickjs-ng/tests/detect_module/0.js +1 -0
  167. package/native/vendor/quickjs-ng/tests/detect_module/1.js +2 -0
  168. package/native/vendor/quickjs-ng/tests/detect_module/2.js +1 -0
  169. package/native/vendor/quickjs-ng/tests/detect_module/3.js +8 -0
  170. package/native/vendor/quickjs-ng/tests/detect_module/4.js +3 -0
  171. package/native/vendor/quickjs-ng/tests/empty.js +0 -0
  172. package/native/vendor/quickjs-ng/tests/fixture_cyclic_import.js +2 -0
  173. package/native/vendor/quickjs-ng/tests/fixture_string_exports.js +12 -0
  174. package/native/vendor/quickjs-ng/tests/function_source.js +14 -0
  175. package/native/vendor/quickjs-ng/tests/microbench.js +1267 -0
  176. package/native/vendor/quickjs-ng/tests/null_or_undefined.js +38 -0
  177. package/native/vendor/quickjs-ng/tests/str-pad-leak.js +5 -0
  178. package/native/vendor/quickjs-ng/tests/test_bigint.js +107 -0
  179. package/native/vendor/quickjs-ng/tests/test_bjson.js +366 -0
  180. package/native/vendor/quickjs-ng/tests/test_builtin.js +1314 -0
  181. package/native/vendor/quickjs-ng/tests/test_closure.js +220 -0
  182. package/native/vendor/quickjs-ng/tests/test_cyclic_import.js +12 -0
  183. package/native/vendor/quickjs-ng/tests/test_domexception.js +35 -0
  184. package/native/vendor/quickjs-ng/tests/test_language.js +755 -0
  185. package/native/vendor/quickjs-ng/tests/test_loop.js +367 -0
  186. package/native/vendor/quickjs-ng/tests/test_queue_microtask.js +39 -0
  187. package/native/vendor/quickjs-ng/tests/test_std.js +340 -0
  188. package/native/vendor/quickjs-ng/tests/test_string_exports.js +25 -0
  189. package/native/vendor/quickjs-ng/tests/test_worker.js +43 -0
  190. package/native/vendor/quickjs-ng/tests/test_worker_module.js +30 -0
  191. package/native/vendor/quickjs-ng/tests.conf +14 -0
  192. package/native/vendor/quickjs-ng/unicode_download.sh +19 -0
  193. package/native/vendor/quickjs-ng/unicode_gen.c +3108 -0
  194. package/native/vendor/quickjs-ng/unicode_gen_def.h +310 -0
  195. package/native/vendor/quickjs-ng/update-version.sh +32 -0
  196. package/native/vendor/webview2/include/WebView2.h +60636 -0
  197. package/native/vendor/webview2/include/WebView2EnvironmentOptions.h +406 -0
  198. package/package.json +33 -0
  199. package/src/backend.ts +139 -0
  200. package/src/build-config.ts +87 -0
  201. package/src/build.ts +276 -0
  202. package/src/common.ts +195 -0
  203. package/src/config.ts +89 -0
  204. package/src/dev.ts +164 -0
  205. package/src/generate.ts +200 -0
  206. package/src/icons.ts +116 -0
  207. package/src/init.ts +190 -0
  208. package/src/package.ts +150 -0
  209. package/src/zapp-cli.ts +263 -0
@@ -0,0 +1,387 @@
1
+ import "../platform.zc";
2
+ import "./webview.zc";
3
+ import "./backend.zc";
4
+
5
+ //> windows: link: -lole32 -lshell32 -luuid -luser32 -lgdi32 -lcomctl32 -lcomdlg32
6
+ //> windows: cflags: -DUNICODE -D_UNICODE
7
+
8
+ import "./worker/mod.zc";
9
+
10
+ fn app_get_config(app_ptr: App*) -> AppConfig;
11
+ fn app_should_quit() -> bool;
12
+
13
+ raw {
14
+ #ifdef _WIN32
15
+ #include <windows.h>
16
+ #include <stdlib.h>
17
+ #include <stdio.h>
18
+ #include <commctrl.h>
19
+
20
+ const wchar_t* ZAPP_WINDOW_CLASS = L"ZappWindowClass";
21
+ static BOOL zapp_window_class_registered = FALSE;
22
+ static BOOL zapp_should_terminate_after_last = FALSE;
23
+ extern bool app_should_quit(void);
24
+ extern void zapp_windows_webview_resize(HWND hwnd);
25
+ extern void zapp_windows_webview_detach(HWND hwnd);
26
+ extern void zapp_windows_webview_notify_position(HWND hwnd);
27
+ extern void zapp_windows_webview_eval_all_ui(wchar_t* wJs);
28
+
29
+ #define WM_ZAPP_HANDLE_MSG (WM_APP + 2)
30
+
31
+ extern void zapp_handle_message(void* app, char* msg);
32
+ extern void* app_get_active(void);
33
+ static DWORD zapp_ui_thread_id = 0;
34
+
35
+ #ifndef ZAPP_EVENT_WINDOW_FOCUS
36
+ #define ZAPP_EVENT_WINDOW_FOCUS 1
37
+ #endif
38
+ #ifndef ZAPP_EVENT_WINDOW_BLUR
39
+ #define ZAPP_EVENT_WINDOW_BLUR 2
40
+ #endif
41
+ #ifndef ZAPP_EVENT_WINDOW_RESIZE
42
+ #define ZAPP_EVENT_WINDOW_RESIZE 3
43
+ #endif
44
+ #ifndef ZAPP_EVENT_WINDOW_MOVE
45
+ #define ZAPP_EVENT_WINDOW_MOVE 4
46
+ #endif
47
+ #ifndef ZAPP_EVENT_WINDOW_CLOSE
48
+ #define ZAPP_EVENT_WINDOW_CLOSE 5
49
+ #endif
50
+ #ifndef ZAPP_EVENT_WINDOW_MINIMIZE
51
+ #define ZAPP_EVENT_WINDOW_MINIMIZE 6
52
+ #endif
53
+ #ifndef ZAPP_EVENT_WINDOW_MAXIMIZE
54
+ #define ZAPP_EVENT_WINDOW_MAXIMIZE 7
55
+ #endif
56
+ #ifndef ZAPP_EVENT_WINDOW_RESTORE
57
+ #define ZAPP_EVENT_WINDOW_RESTORE 8
58
+ #endif
59
+ #ifndef ZAPP_EVENT_WINDOW_FULLSCREEN
60
+ #define ZAPP_EVENT_WINDOW_FULLSCREEN 9
61
+ #endif
62
+ #ifndef ZAPP_EVENT_WINDOW_UNFULLSCREEN
63
+ #define ZAPP_EVENT_WINDOW_UNFULLSCREEN 10
64
+ #endif
65
+ #ifndef ZAPP_EVENT_RESULT_CANCEL
66
+ #define ZAPP_EVENT_RESULT_CANCEL 1
67
+ #endif
68
+
69
+ extern const char* zapp_win_id_for_hwnd(HWND hwnd);
70
+ extern int zapp_window_get_numeric_id(const char* window_id);
71
+ extern int zapp_window_trigger_event_with_data(int id, int event_id, int w, int h, int x, int y);
72
+ extern void zapp_dispatch_window_event_to_bridge_win(const char* window_id, int event_id, int width, int height, int x, int y);
73
+ extern ZappWindowEntry* zapp_window_entry_for_hwnd(HWND hwnd);
74
+
75
+ // Helper to fire both native callback and bridge event for Windows
76
+ static void zapp_fire_window_event_win(HWND hwnd, int event_id, int w, int h, int x, int y) {
77
+ const char* windowId = zapp_win_id_for_hwnd(hwnd);
78
+ if (!windowId) return;
79
+ int numericId = zapp_window_get_numeric_id(windowId);
80
+ if (numericId >= 0)
81
+ zapp_window_trigger_event_with_data(numericId, event_id, w, h, x, y);
82
+ ZappWindowEntry* entry = zapp_window_entry_for_hwnd(hwnd);
83
+ if (entry && entry->bridgeReady) {
84
+ zapp_dispatch_window_event_to_bridge_win(windowId, event_id, w, h, x, y);
85
+ }
86
+ }
87
+
88
+ // -----------------------------------------------------------------------
89
+ // Default system menus (Edit, View, Window) — must be before WndProc
90
+ // -----------------------------------------------------------------------
91
+ #define IDM_EDIT_UNDO 40001
92
+ #define IDM_EDIT_REDO 40002
93
+ #define IDM_EDIT_CUT 40003
94
+ #define IDM_EDIT_COPY 40004
95
+ #define IDM_EDIT_PASTE 40005
96
+ #define IDM_EDIT_SELECTALL 40006
97
+ #define IDM_VIEW_FULLSCREEN 40010
98
+ #define IDM_WIN_MINIMIZE 40020
99
+ #define IDM_WIN_MAXIMIZE 40021
100
+ #define IDM_WIN_CLOSE 40022
101
+
102
+ HMENU zapp_default_menu = NULL;
103
+ HACCEL zapp_accel_table = NULL;
104
+
105
+ extern void windows_window_set_fullscreen(void* window, _Bool on);
106
+
107
+ HMENU zapp_create_default_menu(void) {
108
+ HMENU menuBar = CreateMenu();
109
+
110
+ HMENU editMenu = CreatePopupMenu();
111
+ AppendMenuW(editMenu, MF_STRING, IDM_EDIT_UNDO, L"Undo\tCtrl+Z");
112
+ AppendMenuW(editMenu, MF_STRING, IDM_EDIT_REDO, L"Redo\tCtrl+Y");
113
+ AppendMenuW(editMenu, MF_SEPARATOR, 0, NULL);
114
+ AppendMenuW(editMenu, MF_STRING, IDM_EDIT_CUT, L"Cut\tCtrl+X");
115
+ AppendMenuW(editMenu, MF_STRING, IDM_EDIT_COPY, L"Copy\tCtrl+C");
116
+ AppendMenuW(editMenu, MF_STRING, IDM_EDIT_PASTE, L"Paste\tCtrl+V");
117
+ AppendMenuW(editMenu, MF_SEPARATOR, 0, NULL);
118
+ AppendMenuW(editMenu, MF_STRING, IDM_EDIT_SELECTALL, L"Select All\tCtrl+A");
119
+ AppendMenuW(menuBar, MF_POPUP, (UINT_PTR)editMenu, L"Edit");
120
+
121
+ HMENU viewMenu = CreatePopupMenu();
122
+ AppendMenuW(viewMenu, MF_STRING, IDM_VIEW_FULLSCREEN, L"Fullscreen\tF11");
123
+ AppendMenuW(menuBar, MF_POPUP, (UINT_PTR)viewMenu, L"View");
124
+
125
+ HMENU windowMenu = CreatePopupMenu();
126
+ AppendMenuW(windowMenu, MF_STRING, IDM_WIN_MINIMIZE, L"Minimize");
127
+ AppendMenuW(windowMenu, MF_STRING, IDM_WIN_MAXIMIZE, L"Maximize");
128
+ AppendMenuW(windowMenu, MF_SEPARATOR, 0, NULL);
129
+ AppendMenuW(windowMenu, MF_STRING, IDM_WIN_CLOSE, L"Close\tAlt+F4");
130
+ AppendMenuW(menuBar, MF_POPUP, (UINT_PTR)windowMenu, L"Window");
131
+
132
+ zapp_default_menu = menuBar;
133
+ return menuBar;
134
+ }
135
+
136
+ HACCEL zapp_create_default_accel(void) {
137
+ ACCEL accels[] = {
138
+ { FCONTROL | FVIRTKEY, 'Z', IDM_EDIT_UNDO },
139
+ { FCONTROL | FVIRTKEY, 'Y', IDM_EDIT_REDO },
140
+ { FCONTROL | FVIRTKEY, 'X', IDM_EDIT_CUT },
141
+ { FCONTROL | FVIRTKEY, 'C', IDM_EDIT_COPY },
142
+ { FCONTROL | FVIRTKEY, 'V', IDM_EDIT_PASTE },
143
+ { FCONTROL | FVIRTKEY, 'A', IDM_EDIT_SELECTALL },
144
+ { FVIRTKEY, VK_F11, IDM_VIEW_FULLSCREEN },
145
+ };
146
+ return CreateAcceleratorTableW(accels, sizeof(accels) / sizeof(accels[0]));
147
+ }
148
+
149
+ void zapp_handle_menu_command(HWND hwnd, WORD cmd) {
150
+ switch (cmd) {
151
+ case IDM_EDIT_UNDO:
152
+ case IDM_EDIT_REDO:
153
+ case IDM_EDIT_CUT:
154
+ case IDM_EDIT_COPY:
155
+ case IDM_EDIT_PASTE:
156
+ case IDM_EDIT_SELECTALL: {
157
+ HWND focus = GetFocus();
158
+ if (focus) SendMessageW(focus, WM_COMMAND, cmd, 0);
159
+ break;
160
+ }
161
+ case IDM_VIEW_FULLSCREEN: {
162
+ if (hwnd) {
163
+ LONG style = GetWindowLongW(hwnd, GWL_STYLE);
164
+ BOOL isFS = !(style & WS_OVERLAPPEDWINDOW);
165
+ windows_window_set_fullscreen((void*)hwnd, !isFS);
166
+ }
167
+ break;
168
+ }
169
+ case IDM_WIN_MINIMIZE:
170
+ if (hwnd) ShowWindow(hwnd, SW_MINIMIZE);
171
+ break;
172
+ case IDM_WIN_MAXIMIZE:
173
+ if (hwnd) ShowWindow(hwnd, IsZoomed(hwnd) ? SW_RESTORE : SW_MAXIMIZE);
174
+ break;
175
+ case IDM_WIN_CLOSE:
176
+ if (hwnd) PostMessageW(hwnd, WM_CLOSE, 0, 0);
177
+ break;
178
+ }
179
+ }
180
+
181
+ static LRESULT CALLBACK ZappWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
182
+ switch (msg) {
183
+ case WM_ERASEBKGND:
184
+ return 1;
185
+ case WM_COMMAND: {
186
+ WORD cmd = LOWORD(wParam);
187
+ if (cmd >= 40001 && cmd <= 40099) {
188
+ zapp_handle_menu_command(hwnd, cmd);
189
+ return 0;
190
+ }
191
+ break;
192
+ }
193
+ case WM_ZAPP_EVAL_JS: {
194
+ zapp_windows_webview_eval_all_ui((wchar_t*)lParam);
195
+ return 0;
196
+ }
197
+ case WM_SIZE: {
198
+ zapp_windows_webview_resize(hwnd);
199
+ RECT client;
200
+ GetClientRect(hwnd, &client);
201
+ int w = client.right - client.left;
202
+ int h = client.bottom - client.top;
203
+ RECT frame;
204
+ GetWindowRect(hwnd, &frame);
205
+ int x = frame.left;
206
+ int y = frame.top;
207
+ WORD sizeType = LOWORD(wParam);
208
+ if (sizeType == SIZE_MINIMIZED) {
209
+ zapp_fire_window_event_win(hwnd, ZAPP_EVENT_WINDOW_MINIMIZE, w, h, x, y);
210
+ } else if (sizeType == SIZE_MAXIMIZED) {
211
+ zapp_fire_window_event_win(hwnd, ZAPP_EVENT_WINDOW_MAXIMIZE, w, h, x, y);
212
+ zapp_fire_window_event_win(hwnd, ZAPP_EVENT_WINDOW_RESIZE, w, h, x, y);
213
+ } else if (sizeType == SIZE_RESTORED) {
214
+ zapp_fire_window_event_win(hwnd, ZAPP_EVENT_WINDOW_RESTORE, w, h, x, y);
215
+ zapp_fire_window_event_win(hwnd, ZAPP_EVENT_WINDOW_RESIZE, w, h, x, y);
216
+ } else {
217
+ zapp_fire_window_event_win(hwnd, ZAPP_EVENT_WINDOW_RESIZE, w, h, x, y);
218
+ }
219
+ return 0;
220
+ }
221
+ case WM_MOVE: {
222
+ zapp_windows_webview_notify_position(hwnd);
223
+ RECT rc;
224
+ GetWindowRect(hwnd, &rc);
225
+ int w = rc.right - rc.left;
226
+ int h = rc.bottom - rc.top;
227
+ zapp_fire_window_event_win(hwnd, ZAPP_EVENT_WINDOW_MOVE, w, h, rc.left, rc.top);
228
+ break;
229
+ }
230
+ case WM_MOVING: {
231
+ zapp_windows_webview_notify_position(hwnd);
232
+ break;
233
+ }
234
+ case WM_ACTIVATE: {
235
+ const char* windowId = zapp_win_id_for_hwnd(hwnd);
236
+ if (windowId) {
237
+ int numericId = zapp_window_get_numeric_id(windowId);
238
+ WORD activateState = LOWORD(wParam);
239
+ if (activateState == WA_ACTIVE || activateState == WA_CLICKACTIVE) {
240
+ if (numericId >= 0)
241
+ zapp_window_trigger_event_with_data(numericId, ZAPP_EVENT_WINDOW_FOCUS, 0, 0, 0, 0);
242
+ ZappWindowEntry* entry = zapp_window_entry_for_hwnd(hwnd);
243
+ if (entry && entry->bridgeReady) {
244
+ zapp_dispatch_window_event_to_bridge_win(windowId, ZAPP_EVENT_WINDOW_FOCUS, 0, 0, 0, 0);
245
+ } else if (entry) {
246
+ entry->pendingFocusEvent = TRUE;
247
+ }
248
+ } else if (activateState == WA_INACTIVE) {
249
+ if (numericId >= 0)
250
+ zapp_window_trigger_event_with_data(numericId, ZAPP_EVENT_WINDOW_BLUR, 0, 0, 0, 0);
251
+ zapp_dispatch_window_event_to_bridge_win(windowId, ZAPP_EVENT_WINDOW_BLUR, 0, 0, 0, 0);
252
+ }
253
+ }
254
+ break;
255
+ }
256
+ case WM_DESTROY: {
257
+ zapp_windows_webview_detach(hwnd);
258
+ if (zapp_should_terminate_after_last && app_should_quit()) {
259
+ PostQuitMessage(0);
260
+ }
261
+ return 0;
262
+ }
263
+ case WM_CLOSE: {
264
+ ZappWindowEntry* closeEntry = zapp_window_entry_for_hwnd(hwnd);
265
+ // Force-close bypasses all guards
266
+ if (closeEntry && closeEntry->forceClose) {
267
+ closeEntry->forceClose = FALSE;
268
+ DestroyWindow(hwnd);
269
+ return 0;
270
+ }
271
+ // Check native Zen-C callback
272
+ const char* closeWid = zapp_win_id_for_hwnd(hwnd);
273
+ if (closeWid) {
274
+ int closeNumId = zapp_window_get_numeric_id(closeWid);
275
+ if (closeNumId >= 0) {
276
+ int result = zapp_window_trigger_event_with_data(closeNumId, ZAPP_EVENT_WINDOW_CLOSE, 0, 0, 0, 0);
277
+ if (result == ZAPP_EVENT_RESULT_CANCEL) return 0;
278
+ }
279
+ // Check JS close guard
280
+ if (closeEntry && closeEntry->closeGuarded) {
281
+ zapp_dispatch_window_event_to_bridge_win(closeWid, ZAPP_EVENT_WINDOW_CLOSE, 0, 0, 0, 0);
282
+ return 0;
283
+ }
284
+ }
285
+ DestroyWindow(hwnd);
286
+ return 0;
287
+ }
288
+ }
289
+ return DefWindowProcW(hwnd, msg, wParam, lParam);
290
+ }
291
+
292
+ static void zapp_register_window_class(void) {
293
+ if (zapp_window_class_registered) return;
294
+ WNDCLASSEXW wc = {0};
295
+ wc.cbSize = sizeof(WNDCLASSEXW);
296
+ wc.style = 0;
297
+ wc.lpfnWndProc = ZappWindowProc;
298
+ wc.hInstance = GetModuleHandleW(NULL);
299
+ wc.hCursor = LoadCursorW(NULL, IDC_ARROW);
300
+ wc.hbrBackground = NULL;
301
+ wc.lpszClassName = ZAPP_WINDOW_CLASS;
302
+ wc.lpszMenuName = NULL;
303
+ RegisterClassExW(&wc);
304
+ zapp_window_class_registered = TRUE;
305
+ // Pre-create the default menu and accelerator table
306
+ zapp_create_default_menu();
307
+ zapp_accel_table = zapp_create_default_accel();
308
+ }
309
+
310
+ static BOOL WINAPI zapp_console_ctrl_handler(DWORD ctrlType) {
311
+ if (ctrlType == CTRL_C_EVENT || ctrlType == CTRL_BREAK_EVENT) {
312
+ if (zapp_ui_thread_id) {
313
+ PostThreadMessageW(zapp_ui_thread_id, WM_QUIT, 0, 0);
314
+ }
315
+ return TRUE;
316
+ }
317
+ return FALSE;
318
+ }
319
+
320
+ void zapp_post_to_ui_thread(const char* wire) {
321
+ if (!zapp_ui_thread_id) return;
322
+ PostThreadMessageW(zapp_ui_thread_id, WM_ZAPP_HANDLE_MSG, 0, (LPARAM)_strdup(wire));
323
+ }
324
+
325
+ #endif
326
+ }
327
+
328
+ struct WindowsPlatform {
329
+ initialized: bool;
330
+ }
331
+
332
+ impl Platform for WindowsPlatform {
333
+ fn init(self) -> void {
334
+ if self.initialized {
335
+ return;
336
+ }
337
+ raw {
338
+ #ifdef _WIN32
339
+ HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
340
+ if (FAILED(hr) && hr != S_FALSE && hr != RPC_E_CHANGED_MODE) {
341
+ fprintf(stderr, "[zapp] CoInitializeEx failed: 0x%08lX\n", hr);
342
+ }
343
+ INITCOMMONCONTROLSEX icc = {0};
344
+ icc.dwSize = sizeof(icc);
345
+ icc.dwICC = ICC_STANDARD_CLASSES;
346
+ InitCommonControlsEx(&icc);
347
+ zapp_register_window_class();
348
+ SetConsoleCtrlHandler(zapp_console_ctrl_handler, TRUE);
349
+ #endif
350
+ }
351
+ self.initialized = true;
352
+ }
353
+
354
+ fn run(self, app: App*) -> int {
355
+ self.init();
356
+ let cfg = app_get_config(app);
357
+ raw {
358
+ #ifdef _WIN32
359
+ zapp_should_terminate_after_last =
360
+ cfg.applicationShouldTerminateAfterLastWindowClosed ? TRUE : FALSE;
361
+ #endif
362
+ }
363
+
364
+ raw {
365
+ #ifdef _WIN32
366
+ MSG msg;
367
+ while (GetMessageW(&msg, NULL, 0, 0) > 0) {
368
+ if (msg.hwnd == NULL && msg.message == WM_ZAPP_HANDLE_MSG) {
369
+ char* wire = (char*)msg.lParam;
370
+ zapp_handle_message(app_get_active(), wire);
371
+ free(wire);
372
+ continue;
373
+ }
374
+ if (zapp_accel_table && TranslateAcceleratorW(msg.hwnd, zapp_accel_table, &msg)) {
375
+ continue;
376
+ }
377
+ TranslateMessage(&msg);
378
+ DispatchMessageW(&msg);
379
+ }
380
+ #endif
381
+ }
382
+ return 0;
383
+ }
384
+ }
385
+
386
+ // windows_platform_bind_runtime and windows_platform_handle_worker_bridge
387
+ // are defined in worker/mod.zc