cj-tauri 2.0.0 → 2.1.1
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.
- package/README.md +206 -139
- package/bin/cj-tauri.js +287 -287
- package/cjpm.toml +63 -52
- package/cli/cjpm.toml +22 -22
- package/cli/src/doctor.cj +308 -306
- package/cli/src/main.cj +129 -129
- package/cli/src/manifest.cj +643 -558
- package/cli/src/manifest_test.cj +87 -0
- package/cli/src/project.cj +770 -770
- package/cli/src/resolve.cj +348 -348
- package/cli/src/scaffold.cj +369 -369
- package/cli/src/sync.cj +638 -526
- package/cli/src/util.cj +168 -168
- package/cli/templates/app/README.md +51 -48
- package/cli/templates/app/assets/capabilities/default.json +7 -7
- package/cli/templates/app/assets/ui/index.html +120 -118
- package/cli/templates/app/cj-tauri.toml +32 -22
- package/cli/templates/app/cjpm.toml +34 -34
- package/cli/templates/app/src/main.cj +101 -90
- package/cli/templates/app-react/README.md +56 -56
- package/cli/templates/app-react/assets/capabilities/default.json +7 -7
- package/cli/templates/app-react/assets/ui/index.html +25 -25
- package/cli/templates/app-react/assets/ui/package.json +19 -19
- package/cli/templates/app-react/assets/ui/src/App.css +67 -67
- package/cli/templates/app-react/assets/ui/src/App.jsx +124 -124
- package/cli/templates/app-react/assets/ui/src/main.jsx +6 -6
- package/cli/templates/app-react/assets/ui/vite.config.js +24 -24
- package/cli/templates/app-react/cj-tauri.toml +33 -23
- package/cli/templates/app-react/cjpm.toml +34 -34
- package/cli/templates/app-react/src/main.cj +91 -91
- package/cli/templates/app-vue/README.md +56 -56
- package/cli/templates/app-vue/assets/capabilities/default.json +7 -7
- package/cli/templates/app-vue/assets/ui/index.html +25 -25
- package/cli/templates/app-vue/assets/ui/package.json +18 -18
- package/cli/templates/app-vue/assets/ui/src/App.vue +176 -176
- package/cli/templates/app-vue/assets/ui/src/main.js +4 -4
- package/cli/templates/app-vue/assets/ui/vite.config.js +24 -24
- package/cli/templates/app-vue/cj-tauri.toml +33 -23
- package/cli/templates/app-vue/cjpm.toml +34 -34
- package/cli/templates/app-vue/src/main.cj +91 -91
- package/cli/templates/ohos-skeleton/AppScope/app.json5 +13 -13
- package/cli/templates/ohos-skeleton/AppScope/resources/base/element/string.json +8 -8
- package/cli/templates/ohos-skeleton/AppScope/resources/base/media/layered_image.json +6 -6
- package/cli/templates/ohos-skeleton/README.md +84 -79
- package/cli/templates/ohos-skeleton/build-hap.sh +15 -0
- package/cli/templates/ohos-skeleton/build-profile.json5 +46 -46
- package/cli/templates/ohos-skeleton/entry/build-profile.json5 +26 -26
- package/cli/templates/ohos-skeleton/entry/cjpm.toml +51 -43
- package/cli/templates/ohos-skeleton/entry/hvigorfile.ts +6 -6
- package/cli/templates/ohos-skeleton/entry/oh-package.json5 +9 -9
- package/cli/templates/ohos-skeleton/entry/src/main/cangjie/ability_stage.cj +17 -17
- package/cli/templates/ohos-skeleton/entry/src/main/cangjie/app_host.cj +94 -94
- package/cli/templates/ohos-skeleton/entry/src/main/cangjie/dialog_host.cj +217 -0
- package/cli/templates/ohos-skeleton/entry/src/main/cangjie/index.cj +527 -167
- package/cli/templates/ohos-skeleton/entry/src/main/cangjie/main_ability.cj +139 -139
- package/cli/templates/ohos-skeleton/entry/src/main/module.json5 +57 -49
- package/cli/templates/ohos-skeleton/entry/src/main/resources/base/element/color.json +8 -8
- package/cli/templates/ohos-skeleton/entry/src/main/resources/base/element/string.json +16 -16
- package/cli/templates/ohos-skeleton/entry/src/main/resources/base/media/layered_image.json +6 -6
- package/cli/templates/ohos-skeleton/entry/src/main/resources/base/profile/main_pages.json +2 -2
- package/cli/templates/ohos-skeleton/entry/src/main/resources/rawfile/capabilities.json +6 -6
- package/cli/templates/ohos-skeleton/entry/src/main/resources/rawfile/index.html +92 -92
- package/cli/templates/ohos-skeleton/hvigor/hvigor-config.json5 +5 -5
- package/cli/templates/ohos-skeleton/hvigorfile.ts +6 -6
- package/cli/templates/ohos-skeleton/oh-package.json5 +10 -10
- package/native/build_win.bat +62 -62
- package/native/core/bridge_core.c +1681 -1626
- package/native/core/bridge_core.h +675 -618
- package/native/core/bridge_js.h +108 -108
- package/native/platforms/harmonyos/README.md +115 -6
- package/native/platforms/linux/bridge_linux.c +2787 -2485
- package/native/platforms/windows/bridge_win.c +3745 -3248
- package/native/tests/gtk_threading_probe.c +143 -143
- package/native/tests/test_bridge_core.c +1339 -1228
- package/package.json +53 -53
- package/src/api_system.cj +67 -67
- package/src/app.cj +335 -969
- package/src/app_events.cj +166 -0
- package/src/app_host_ops.cj +287 -0
- package/src/app_run.cj +283 -0
- package/src/app_spec.cj +76 -76
- package/src/arkweb_menu.cj +216 -0
- package/src/arkweb_script.cj +142 -142
- package/src/capability.cj +409 -409
- package/src/clipboard_bridge.cj +178 -0
- package/src/dialog_spec.cj +79 -0
- package/src/dragdrop.cj +26 -26
- package/src/embedded_assets.cj +98 -98
- package/src/host.cj +752 -607
- package/src/host_arkweb.cj +924 -778
- package/src/host_webkit.cj +663 -570
- package/src/host_webview2.cj +663 -570
- package/src/hotkey.cj +66 -66
- package/src/ipc_hub.cj +401 -337
- package/src/ipc_message.cj +286 -286
- package/src/launch.cj +62 -62
- package/src/logging.cj +127 -127
- package/src/menu.cj +197 -197
- package/src/platform/platform_app_context.cj +77 -77
- package/src/platform/platform_assets.cj +33 -33
- package/src/platform/platform_discover.cj +176 -176
- package/src/platform/platform_env.cj +29 -29
- package/src/platform/platform_feature.cj +31 -31
- package/src/platform/platform_page_source.cj +87 -87
- package/src/platform/platform_target_info.cj +32 -32
- package/src/platform_host_provider.cj +87 -87
- package/src/plugin.cj +333 -333
- package/src/plugins/clipboard/plugin_clipboard.cj +152 -152
- package/src/plugins/dialog/plugin_dialog.cj +209 -209
- package/src/plugins/fs/plugin_fs.cj +105 -1
- package/src/plugins/http/http_backend.cj +131 -0
- package/src/plugins/http/http_desktop.cj +195 -0
- package/src/plugins/http/http_ohos.cj +204 -0
- package/src/plugins/http/plugin_http.cj +310 -459
- package/src/plugins/log/plugin_log.cj +105 -105
- package/src/plugins/menu/plugin_menu.cj +158 -158
- package/src/plugins/notification/plugin_notification.cj +154 -154
- package/src/plugins/serial/plugin_serial.cj +458 -454
- package/src/plugins/serial/serial_bridge.cj +194 -194
- package/src/plugins/serial/serial_manager_ohos.cj +92 -0
- package/src/plugins/serial/serial_ohos.cj +529 -0
- package/src/plugins/shell/plugin_shell.cj +258 -258
- package/src/plugins/sqlite/plugin_sqlite.cj +705 -710
- package/src/plugins/sqlite/sqlite_ffi.cj +206 -211
- package/src/plugins/ws/plugin_ws.cj +488 -470
- package/src/process_hidden.cj +174 -174
- package/src/scope.cj +391 -391
- package/src/shell_event.cj +69 -69
- package/src/tests/app_spec_test.cj +130 -127
- package/src/tests/capability_test.cj +243 -243
- package/src/tests/dialog_spec_test.cj +73 -0
- package/src/tests/fake_host.cj +201 -201
- package/src/tests/ipc_hub_test.cj +563 -487
- package/src/tests/logging_test.cj +62 -62
- package/src/tests/platform_contract_test.cj +264 -251
- package/src/tests/plugin_clipboard_test.cj +222 -222
- package/src/tests/plugin_dialog_test.cj +237 -237
- package/src/tests/plugin_fs_test.cj +207 -0
- package/src/tests/plugin_http_test.cj +124 -124
- package/src/tests/plugin_notification_test.cj +205 -205
- package/src/tests/plugin_serial_test.cj +48 -0
- package/src/tests/plugin_test.cj +605 -585
- package/src/tests/plugin_ws_test.cj +40 -40
- package/src/tests/process_hidden_test.cj +129 -129
- package/src/tests/scope_test.cj +350 -350
- package/src/tests/system_host_test.cj +99 -81
- package/src/tests/urlutil_test.cj +53 -53
- package/src/tests/version_test.cj +75 -75
- package/src/tests/window_registry_test.cj +123 -123
- package/src/tray.cj +90 -90
- package/src/urlutil.cj +159 -159
- package/src/version.cj +44 -44
- package/src/window.cj +51 -51
- package/src/window_registry.cj +116 -116
- package/prebuilt/win32-x64/cj-tauri.exe +0 -0
- package/src/plugins/serial/serial_ohos_stub.cj +0 -61
- package/src/plugins/sqlite/sqlite_ohos_stub.cj +0 -91
package/src/host_webview2.cj
CHANGED
|
@@ -1,570 +1,663 @@
|
|
|
1
|
-
package cjTauri
|
|
2
|
-
|
|
3
|
-
// Windows 侧才用得上(类整体门禁在 Windows):加同款门禁,免得 Linux 构建把这条当「未使用 import」清掉
|
|
4
|
-
@When[os == "Windows"]
|
|
5
|
-
import std.collection.*
|
|
6
|
-
|
|
7
|
-
// 页面来源契约(load(source) 收敛,RFC §4.3):同款门禁,免得别的目标把这条当未使用清掉
|
|
8
|
-
@When[os == "Windows"]
|
|
9
|
-
import cjTauri.platform.*
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* C 桥 FFI 声明(native/libcjtbridge.dll)
|
|
13
|
-
* Win32 窗口 + WebView2(Edge Chromium)在 C 桥的宿主线程内运行(见 native/bridge_win.c 头注释)。
|
|
14
|
-
* 与 Linux 端(host_webkit.cj)同名同签名,两端宿主实现同构。
|
|
15
|
-
*
|
|
16
|
-
* 句柄制(批次 1):宿主状态在 C 侧按句柄隔离,导出一律首参收句柄(`cj_host*`)。
|
|
17
|
-
* 句柄内存由 C 侧分配/回收(create 分配、destroy 释放)——跨 FFI 绝不「这边分配那边释放」
|
|
18
|
-
* (Windows 上 CRT 与仓颉运行时不是同一个分配器);生命周期约定见
|
|
19
|
-
* docs/架构演进-多平台与多窗口.md §6.1。
|
|
20
|
-
*/
|
|
21
|
-
@When[os == "Windows"]
|
|
22
|
-
@C
|
|
23
|
-
foreign func cj_bridge_create(): CPointer<Unit>
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* 释放宿主编:对空指针安全、幂等;调用后该句柄不可再用
|
|
27
|
-
*/
|
|
28
|
-
@When[os == "Windows"]
|
|
29
|
-
@C
|
|
30
|
-
foreign func cj_bridge_destroy(h: CPointer<Unit>): Unit
|
|
31
|
-
|
|
32
|
-
@When[os == "Windows"]
|
|
33
|
-
@C
|
|
34
|
-
foreign func cj_bridge_init(h: CPointer<Unit>, m: CFunc<(CString) -> Unit>, d: CFunc<(CPointer<Unit>) -> Unit>): Unit
|
|
35
|
-
|
|
36
|
-
@When[os == "Windows"]
|
|
37
|
-
@C
|
|
38
|
-
foreign func cj_bridge_start(h: CPointer<Unit>, html: CString): Unit
|
|
39
|
-
|
|
40
|
-
@When[os == "Windows"]
|
|
41
|
-
@C
|
|
42
|
-
foreign func cj_bridge_load_url(h: CPointer<Unit>, url: CString): Unit
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* 注册一段预执行脚本(插件 jsShim 等):须在 cj_bridge_start 之前调用,桥在 document-start 注入
|
|
46
|
-
*/
|
|
47
|
-
@When[os == "Windows"]
|
|
48
|
-
@C
|
|
49
|
-
foreign func cj_bridge_add_init_script(h: CPointer<Unit>, js: CString): Unit
|
|
50
|
-
|
|
51
|
-
@When[os == "Windows"]
|
|
52
|
-
@C
|
|
53
|
-
foreign func cj_bridge_reload(h: CPointer<Unit>): Unit
|
|
54
|
-
|
|
55
|
-
@When[os == "Windows"]
|
|
56
|
-
@C
|
|
57
|
-
foreign func cj_bridge_set_window(h: CPointer<Unit>, title: CString, width: Int32, height: Int32): Unit
|
|
58
|
-
|
|
59
|
-
@When[os == "Windows"]
|
|
60
|
-
@C
|
|
61
|
-
foreign func cj_bridge_set_devtools(h: CPointer<Unit>, enabled: Int32): Unit
|
|
62
|
-
|
|
63
|
-
@When[os == "Windows"]
|
|
64
|
-
@C
|
|
65
|
-
foreign func cj_bridge_set_icon(h: CPointer<Unit>, path: CString): Unit
|
|
66
|
-
|
|
67
|
-
@When[os == "Windows"]
|
|
68
|
-
@C
|
|
69
|
-
foreign func cj_bridge_open_devtools(h: CPointer<Unit>): Unit
|
|
70
|
-
|
|
71
|
-
@When[os == "Windows"]
|
|
72
|
-
@C
|
|
73
|
-
foreign func cj_bridge_set_dialog_callback(h: CPointer<Unit>, cb: CFunc<(CPointer<Unit>, CString) -> Unit>): Unit
|
|
74
|
-
|
|
75
|
-
/**
|
|
76
|
-
*
|
|
77
|
-
*
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
@
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
@
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
@
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
@
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
@When[os == "Windows"]
|
|
120
|
-
@C
|
|
121
|
-
foreign func
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
public
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
//
|
|
291
|
-
this.ensureHandle()
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
var e: Int32 = 0
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
}
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
}
|
|
361
|
-
|
|
362
|
-
public func
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
}
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
}
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
}
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
public func
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
}
|
|
513
|
-
|
|
514
|
-
public func
|
|
515
|
-
this.
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
this.handle
|
|
558
|
-
|
|
559
|
-
}
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
1
|
+
package cjTauri
|
|
2
|
+
|
|
3
|
+
// Windows 侧才用得上(类整体门禁在 Windows):加同款门禁,免得 Linux 构建把这条当「未使用 import」清掉
|
|
4
|
+
@When[os == "Windows"]
|
|
5
|
+
import std.collection.*
|
|
6
|
+
|
|
7
|
+
// 页面来源契约(load(source) 收敛,RFC §4.3):同款门禁,免得别的目标把这条当未使用清掉
|
|
8
|
+
@When[os == "Windows"]
|
|
9
|
+
import cjTauri.platform.*
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* C 桥 FFI 声明(native/libcjtbridge.dll)
|
|
13
|
+
* Win32 窗口 + WebView2(Edge Chromium)在 C 桥的宿主线程内运行(见 native/bridge_win.c 头注释)。
|
|
14
|
+
* 与 Linux 端(host_webkit.cj)同名同签名,两端宿主实现同构。
|
|
15
|
+
*
|
|
16
|
+
* 句柄制(批次 1):宿主状态在 C 侧按句柄隔离,导出一律首参收句柄(`cj_host*`)。
|
|
17
|
+
* 句柄内存由 C 侧分配/回收(create 分配、destroy 释放)——跨 FFI 绝不「这边分配那边释放」
|
|
18
|
+
* (Windows 上 CRT 与仓颉运行时不是同一个分配器);生命周期约定见
|
|
19
|
+
* docs/架构演进-多平台与多窗口.md §6.1。
|
|
20
|
+
*/
|
|
21
|
+
@When[os == "Windows"]
|
|
22
|
+
@C
|
|
23
|
+
foreign func cj_bridge_create(): CPointer<Unit>
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* 释放宿主编:对空指针安全、幂等;调用后该句柄不可再用
|
|
27
|
+
*/
|
|
28
|
+
@When[os == "Windows"]
|
|
29
|
+
@C
|
|
30
|
+
foreign func cj_bridge_destroy(h: CPointer<Unit>): Unit
|
|
31
|
+
|
|
32
|
+
@When[os == "Windows"]
|
|
33
|
+
@C
|
|
34
|
+
foreign func cj_bridge_init(h: CPointer<Unit>, m: CFunc<(CString) -> Unit>, d: CFunc<(CPointer<Unit>) -> Unit>): Unit
|
|
35
|
+
|
|
36
|
+
@When[os == "Windows"]
|
|
37
|
+
@C
|
|
38
|
+
foreign func cj_bridge_start(h: CPointer<Unit>, html: CString): Unit
|
|
39
|
+
|
|
40
|
+
@When[os == "Windows"]
|
|
41
|
+
@C
|
|
42
|
+
foreign func cj_bridge_load_url(h: CPointer<Unit>, url: CString): Unit
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* 注册一段预执行脚本(插件 jsShim 等):须在 cj_bridge_start 之前调用,桥在 document-start 注入
|
|
46
|
+
*/
|
|
47
|
+
@When[os == "Windows"]
|
|
48
|
+
@C
|
|
49
|
+
foreign func cj_bridge_add_init_script(h: CPointer<Unit>, js: CString): Unit
|
|
50
|
+
|
|
51
|
+
@When[os == "Windows"]
|
|
52
|
+
@C
|
|
53
|
+
foreign func cj_bridge_reload(h: CPointer<Unit>): Unit
|
|
54
|
+
|
|
55
|
+
@When[os == "Windows"]
|
|
56
|
+
@C
|
|
57
|
+
foreign func cj_bridge_set_window(h: CPointer<Unit>, title: CString, width: Int32, height: Int32): Unit
|
|
58
|
+
|
|
59
|
+
@When[os == "Windows"]
|
|
60
|
+
@C
|
|
61
|
+
foreign func cj_bridge_set_devtools(h: CPointer<Unit>, enabled: Int32): Unit
|
|
62
|
+
|
|
63
|
+
@When[os == "Windows"]
|
|
64
|
+
@C
|
|
65
|
+
foreign func cj_bridge_set_icon(h: CPointer<Unit>, path: CString): Unit
|
|
66
|
+
|
|
67
|
+
@When[os == "Windows"]
|
|
68
|
+
@C
|
|
69
|
+
foreign func cj_bridge_open_devtools(h: CPointer<Unit>): Unit
|
|
70
|
+
|
|
71
|
+
@When[os == "Windows"]
|
|
72
|
+
@C
|
|
73
|
+
foreign func cj_bridge_set_dialog_callback(h: CPointer<Unit>, cb: CFunc<(CPointer<Unit>, CString) -> Unit>): Unit
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* 同窗内嵌视图(PLT-006):create 返回视图句柄(> 0 有效,0 = 平台未就绪 / 不支持)。
|
|
77
|
+
* 五条都只是「投递」——桥把动作 PostMessage 到宿主 UI 线程执行,句柄当场返回,
|
|
78
|
+
* 所以 create 成功不代表内容已经出来(真正的 controller 稍后才建)。
|
|
79
|
+
*/
|
|
80
|
+
@When[os == "Windows"]
|
|
81
|
+
@C
|
|
82
|
+
foreign func cj_bridge_view_create(h: CPointer<Unit>, url: CString,
|
|
83
|
+
x: Int32, y: Int32, width: Int32, height: Int32): Int64
|
|
84
|
+
|
|
85
|
+
@When[os == "Windows"]
|
|
86
|
+
@C
|
|
87
|
+
foreign func cj_bridge_view_set_visible(h: CPointer<Unit>, view: Int64, visible: Int32): Unit
|
|
88
|
+
|
|
89
|
+
@When[os == "Windows"]
|
|
90
|
+
@C
|
|
91
|
+
foreign func cj_bridge_view_set_bounds(h: CPointer<Unit>, view: Int64,
|
|
92
|
+
x: Int32, y: Int32, width: Int32, height: Int32): Unit
|
|
93
|
+
|
|
94
|
+
@When[os == "Windows"]
|
|
95
|
+
@C
|
|
96
|
+
foreign func cj_bridge_view_navigate(h: CPointer<Unit>, view: Int64, url: CString): Unit
|
|
97
|
+
|
|
98
|
+
@When[os == "Windows"]
|
|
99
|
+
@C
|
|
100
|
+
foreign func cj_bridge_view_destroy(h: CPointer<Unit>, view: Int64): Unit
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* 原生对话框(阻塞式):kind 0=打开文件 1=保存文件 2=info 3=warning 4=error 5=confirm。
|
|
104
|
+
* 返回 1 = 用户确认;文件类选中路径经 cj_bridge_set_dialog_callback 注册的回调送回。
|
|
105
|
+
*/
|
|
106
|
+
@When[os == "Windows"]
|
|
107
|
+
@C
|
|
108
|
+
foreign func cj_bridge_show_dialog(h: CPointer<Unit>, kind: Int32, title: CString, message: CString,
|
|
109
|
+
filter: CString): Int32
|
|
110
|
+
|
|
111
|
+
@When[os == "Windows"]
|
|
112
|
+
@C
|
|
113
|
+
foreign func cj_bridge_run_js(h: CPointer<Unit>, js: CString): Unit
|
|
114
|
+
|
|
115
|
+
@When[os == "Windows"]
|
|
116
|
+
@C
|
|
117
|
+
foreign func cj_bridge_quit(h: CPointer<Unit>): Unit
|
|
118
|
+
|
|
119
|
+
@When[os == "Windows"]
|
|
120
|
+
@C
|
|
121
|
+
foreign func cj_bridge_is_ready(h: CPointer<Unit>): Int32
|
|
122
|
+
|
|
123
|
+
@When[os == "Windows"]
|
|
124
|
+
@C
|
|
125
|
+
foreign func cj_bridge_should_quit(h: CPointer<Unit>): Int32
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* 菜单栏(RFC-002 §5.4 的线路文本):空串 = 清空。未就绪时桥只记下,建窗时一次建好。
|
|
129
|
+
*/
|
|
130
|
+
@When[os == "Windows"]
|
|
131
|
+
@C
|
|
132
|
+
foreign func cj_bridge_set_menu(h: CPointer<Unit>, wire: CString): Unit
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* 运行期改单个菜单项的状态(按 id 找;找不到只记日志)
|
|
136
|
+
*/
|
|
137
|
+
@When[os == "Windows"]
|
|
138
|
+
@C
|
|
139
|
+
foreign func cj_bridge_set_menu_item_state(h: CPointer<Unit>, id: CString, enabled: Int32,
|
|
140
|
+
checked: Int32): Unit
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* 窗口顶部副标题:Windows 侧如实降级(返回 -4,能力位 CJ_CAP_SUBTITLE 不置位)。
|
|
144
|
+
* 同名同签名保留是为了上层不出现平台分支(AGENTS §2 的第一条)。
|
|
145
|
+
*/
|
|
146
|
+
@When[os == "Windows"]
|
|
147
|
+
@C
|
|
148
|
+
foreign func cj_bridge_set_titlebar_subtitle(h: CPointer<Unit>, text: CString): Int32
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* 拖放策略(RFC-002 §5):Windows 侧当前为桩(能力位如实不置位),同名同签名保上层零平台分支
|
|
152
|
+
*/
|
|
153
|
+
@When[os == "Windows"]
|
|
154
|
+
@C
|
|
155
|
+
foreign func cj_bridge_set_drag_drop(h: CPointer<Unit>, enabled: Int32, files: Int32): Unit
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* 全局快捷键(RFC-003 第 5 期):Windows 侧走 `RegisterHotKey`(见 native/platforms/windows/
|
|
159
|
+
* bridge_win.c),wire 词法与 Linux 同规(Ctrl/Alt/Shift/Super + 常用键名),触发经 on_shell 回投
|
|
160
|
+
*/
|
|
161
|
+
@When[os == "Windows"]
|
|
162
|
+
@C
|
|
163
|
+
foreign func cj_bridge_set_global_hotkeys(h: CPointer<Unit>, wire: CString): Unit
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* 托盘(RFC-002 §7.C):Windows 侧走 `Shell_NotifyIconW`(菜单是 CreatePopupMenu,只弹不挂窗口),
|
|
167
|
+
* 点击与 Linux 同信封回投 `{"kind":"tray","id":…}`
|
|
168
|
+
*/
|
|
169
|
+
@When[os == "Windows"]
|
|
170
|
+
@C
|
|
171
|
+
foreign func cj_bridge_set_tray(h: CPointer<Unit>, wire: CString): Unit
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* 窗口可见性(`show()` / `hide()` 的 C 侧落点):start 之前调只记 pending,就绪后投 UI 线程执行
|
|
175
|
+
*/
|
|
176
|
+
@When[os == "Windows"]
|
|
177
|
+
@C
|
|
178
|
+
foreign func cj_bridge_set_window_visible(h: CPointer<Unit>, visible: Int32): Unit
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* 最小化到托盘策略位(须在 start 之前调):窗口过程据此把「最小化」改写成「隐藏」
|
|
182
|
+
*/
|
|
183
|
+
@When[os == "Windows"]
|
|
184
|
+
@C
|
|
185
|
+
foreign func cj_bridge_set_minimize_to_tray(h: CPointer<Unit>, enabled: Int32): Unit
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* 把 h 挂到 owner 下(owned window):不重复占任务栏、跟随属主显隐
|
|
189
|
+
*
|
|
190
|
+
* 与 set_window_visible 同形——都要求两个句柄都已创建;owner 为空指针时桥侧不动。
|
|
191
|
+
*/
|
|
192
|
+
@When[os == "Windows"]
|
|
193
|
+
@C
|
|
194
|
+
foreign func cj_bridge_set_owner_window(h: CPointer<Unit>, owner: CPointer<Unit>): Unit
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* shell 事件回调(菜单点击等):首参是宿主句柄,多窗口靠它分辨事件属于哪个窗口
|
|
198
|
+
*/
|
|
199
|
+
@When[os == "Windows"]
|
|
200
|
+
@C
|
|
201
|
+
foreign func cj_bridge_set_shell_callback(h: CPointer<Unit>,
|
|
202
|
+
cb: CFunc<(CPointer<Unit>, CString) -> Unit>): Unit
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* 宿主能力位(CJ_CAP_* 的按位或):未 init 返回 0
|
|
206
|
+
*/
|
|
207
|
+
@When[os == "Windows"]
|
|
208
|
+
@C
|
|
209
|
+
foreign func cj_bridge_host_capabilities(h: CPointer<Unit>): Int32
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* 句柄同一性判定(返回 1 = 同一个宿主):仓颉侧 CPointer 不能比较,判定交回 C 侧
|
|
213
|
+
*/
|
|
214
|
+
@When[os == "Windows"]
|
|
215
|
+
@C
|
|
216
|
+
foreign func cj_bridge_host_eq(a: CPointer<Unit>, b: CPointer<Unit>): Int32
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Windows WebView2 宿主实现:通过 C 桥驱动
|
|
220
|
+
*/
|
|
221
|
+
@When[os == "Windows"]
|
|
222
|
+
public class WebView2Host <: WebViewHost {
|
|
223
|
+
// 消息回调:宿主线程(原生 Win32 消息循环)→ 仓颉
|
|
224
|
+
public var onMessage: (String) -> Unit = { _ => }
|
|
225
|
+
// 销毁回调(应用经 setDestroyHandler 装配;由 C 桥按句柄认领,多窗口不串)
|
|
226
|
+
public var onDestroy: () -> Unit = { => }
|
|
227
|
+
// 本窗口文件对话框的结果:C 桥按句柄经路由回调写入(两窗各写各的,不许串台)
|
|
228
|
+
private var dialogResult: String = ""
|
|
229
|
+
// 本窗口的 shell 事件(菜单点击等)回调:TauriApp 装配时经 setShellHandler 覆盖它做分发,
|
|
230
|
+
// 未覆盖时只留一行 stderr——菜单点了没人管,至少能在日志里看见。
|
|
231
|
+
public var shellHandler: (String) -> Unit = { json =>
|
|
232
|
+
eprintln("[cj-tauri] shell event (no handler): ${json}")
|
|
233
|
+
}
|
|
234
|
+
// 窗口配置(标题 / 尺寸),start() 前由 TauriApp 注入
|
|
235
|
+
private var config: WindowConfig = WindowConfig()
|
|
236
|
+
// 预执行脚本(插件 jsShim 等):start 前收集,prepareHost 一次性交给桥,桥在 document-start 注入
|
|
237
|
+
private var initScripts = ArrayList<String>()
|
|
238
|
+
// 宿主编(C 侧分配):空指针 = 尚未创建;dispose() 后置空
|
|
239
|
+
private var handle: CPointer<Unit> = CPointer<Unit>()
|
|
240
|
+
// 本窗口的 label(字段名不叫 label:接口有同名方法)。单窗口阶段是常量,
|
|
241
|
+
// 与 TauriApp 注册的 WindowRecord.label 一致;多窗口时由构造参数给定。
|
|
242
|
+
private let windowLabel: String
|
|
243
|
+
// 资产解析器:装配层在 load 前注入(None = 按 cwd 相对路径读盘,与批次 1 行为等价)
|
|
244
|
+
private var assetResolver: Option<AssetResolver> = None
|
|
245
|
+
|
|
246
|
+
public init() {
|
|
247
|
+
this.windowLabel = DEFAULT_WINDOW_LABEL
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* 带 label 构造(多窗口):label 必须与 TauriApp 注册表里登记的那个一致,
|
|
252
|
+
* 页面侧的 `window.__CJ_TAURI_LABEL__` 也取同一个值(由 TauriApp 注入)。
|
|
253
|
+
*/
|
|
254
|
+
public init(label: String) {
|
|
255
|
+
this.windowLabel = label
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
public func label(): String {
|
|
259
|
+
return this.windowLabel
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
public func setMessageHandler(handler: (String) -> Unit): Unit {
|
|
263
|
+
this.onMessage = handler
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
public func setWindowConfig(config: WindowConfig): Unit {
|
|
267
|
+
this.config = config
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
public func setDevTools(enabled: Bool): Unit {
|
|
271
|
+
this.config.devTools = enabled
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
public func addInitScript(js: String): Unit {
|
|
275
|
+
// 空串忽略(插件没写 shim 时不必占位,桥侧也会再挡一次)
|
|
276
|
+
if (js.size > 0) {
|
|
277
|
+
this.initScripts.add(js)
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
public func openDevTools(): Unit {
|
|
282
|
+
unsafe {
|
|
283
|
+
cj_bridge_open_devtools(this.handle)
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
// ===== 同窗内嵌视图(PLT-006):桥侧把动作投回 UI 线程,这里只是转发 =====
|
|
288
|
+
|
|
289
|
+
public func createEmbeddedView(url: String, x: Int32, y: Int32, width: Int32, height: Int32): Int64 {
|
|
290
|
+
// 窗口没就绪时桥会如实回 0 并打一行 stderr(不是崩溃路径)
|
|
291
|
+
this.ensureHandle()
|
|
292
|
+
unsafe {
|
|
293
|
+
return cj_bridge_view_create(this.handle, LibC.mallocCString(url), x, y, width, height)
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
public func setEmbeddedViewVisible(view: Int64, visible: Bool): Unit {
|
|
298
|
+
var flag: Int32 = 0
|
|
299
|
+
if (visible) {
|
|
300
|
+
flag = 1
|
|
301
|
+
}
|
|
302
|
+
unsafe {
|
|
303
|
+
cj_bridge_view_set_visible(this.handle, view, flag)
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
public func setEmbeddedViewBounds(view: Int64, x: Int32, y: Int32, width: Int32, height: Int32): Unit {
|
|
308
|
+
unsafe {
|
|
309
|
+
cj_bridge_view_set_bounds(this.handle, view, x, y, width, height)
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
public func navigateEmbeddedView(view: Int64, url: String): Unit {
|
|
314
|
+
unsafe {
|
|
315
|
+
cj_bridge_view_navigate(this.handle, view, LibC.mallocCString(url))
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
public func destroyEmbeddedView(view: Int64): Unit {
|
|
320
|
+
unsafe {
|
|
321
|
+
cj_bridge_view_destroy(this.handle, view)
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
public func setMenu(wire: String): Unit {
|
|
326
|
+
// 句柄先建出来:setMenu 允许在 start() 之前调——文本由桥记着,建窗时一次建好
|
|
327
|
+
this.ensureHandle()
|
|
328
|
+
unsafe {
|
|
329
|
+
cj_bridge_set_menu(this.handle, LibC.mallocCString(wire))
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
public func setMenuItemState(id: String, enabled: Bool, checked: Bool): Unit {
|
|
334
|
+
if (this.handle.isNull()) {
|
|
335
|
+
// 还没建宿主就谈不上「改状态」:静默返回,不拿空句柄去 FFI
|
|
336
|
+
return
|
|
337
|
+
}
|
|
338
|
+
var e: Int32 = 0
|
|
339
|
+
var c: Int32 = 0
|
|
340
|
+
if (enabled) {
|
|
341
|
+
e = 1
|
|
342
|
+
}
|
|
343
|
+
if (checked) {
|
|
344
|
+
c = 1
|
|
345
|
+
}
|
|
346
|
+
unsafe {
|
|
347
|
+
cj_bridge_set_menu_item_state(this.handle, LibC.mallocCString(id), e, c)
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
public func setTitlebarSubtitle(text: String): Unit {
|
|
352
|
+
if (this.handle.isNull()) {
|
|
353
|
+
return
|
|
354
|
+
}
|
|
355
|
+
unsafe {
|
|
356
|
+
// 本平台如实降级(桥返回 -4,能力位不含 CJ_CAP_SUBTITLE):这里不当作错误刷屏,
|
|
357
|
+
// 应用据 hostCapabilities().subtitle 自己就不会依赖这条通道
|
|
358
|
+
let _ = cj_bridge_set_titlebar_subtitle(this.handle, LibC.mallocCString(text))
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
public func setDragDropPolicy(enabled: Bool, files: Bool): Unit {
|
|
363
|
+
// 与 setMenu 同形:允许在 start() 之前调。Windows 侧桥当前是桩(能力位如实不置位),
|
|
364
|
+
// 但仓颉侧 API 与调用点不写平台分支——实机轮补 IDropTarget 后上层零改动
|
|
365
|
+
this.ensureHandle()
|
|
366
|
+
var en: Int32 = 0
|
|
367
|
+
var fi: Int32 = 0
|
|
368
|
+
if (enabled) {
|
|
369
|
+
en = 1
|
|
370
|
+
}
|
|
371
|
+
if (files) {
|
|
372
|
+
fi = 1
|
|
373
|
+
}
|
|
374
|
+
unsafe {
|
|
375
|
+
cj_bridge_set_drag_drop(this.handle, en, fi)
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
public func setGlobalHotkeys(wire: String): Unit {
|
|
380
|
+
// 与 setMenu 同形:允许在 start() 之前调。Windows 侧桥当前是桩(能力位如实不置位),
|
|
381
|
+
// 仓颉侧 API 不写平台分支——实机轮补 RegisterHotKey 后上层零改动
|
|
382
|
+
this.ensureHandle()
|
|
383
|
+
unsafe {
|
|
384
|
+
cj_bridge_set_global_hotkeys(this.handle, LibC.mallocCString(wire))
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
public func setTray(wire: String): Unit {
|
|
389
|
+
// 与 setMenu 同形:允许在 start() 之前调。Windows 侧桥当前是桩(能力位如实不置位),
|
|
390
|
+
// 仓颉侧 API 不写平台分支——实机轮补 Shell_NotifyIconW 后上层零改动
|
|
391
|
+
this.ensureHandle()
|
|
392
|
+
unsafe {
|
|
393
|
+
cj_bridge_set_tray(this.handle, LibC.mallocCString(wire))
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
public func setOwnerWindow(ownerLabel: String): Unit {
|
|
398
|
+
if (ownerLabel.size == 0) {
|
|
399
|
+
return
|
|
400
|
+
}
|
|
401
|
+
// 与 setWindowVisible 同形:允许在 start() 之前调(桥记 pending,建窗时定稿)
|
|
402
|
+
this.ensureHandle()
|
|
403
|
+
match (HostGlobals.handleOfLabel(ownerLabel)) {
|
|
404
|
+
case Some(ownerHandle) =>
|
|
405
|
+
unsafe {
|
|
406
|
+
cj_bridge_set_owner_window(this.handle, ownerHandle)
|
|
407
|
+
}
|
|
408
|
+
case None =>
|
|
409
|
+
// 外观修饰失败不该拦着开窗,但要在日志里留凭证
|
|
410
|
+
eprintln("[cj-tauri] setOwnerWindow(${ownerLabel}): 该窗口尚未登记,跳过")
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
public func setWindowVisible(visible: Bool): Unit {
|
|
415
|
+
// 与 setTray 同形:允许在 start() 之前调(桥记 pending,建窗时定稿);就绪后投宿主 UI 线程
|
|
416
|
+
this.ensureHandle()
|
|
417
|
+
var v: Int32 = 0
|
|
418
|
+
if (visible) {
|
|
419
|
+
v = 1
|
|
420
|
+
}
|
|
421
|
+
unsafe {
|
|
422
|
+
cj_bridge_set_window_visible(this.handle, v)
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
public func setMinimizeToTray(enabled: Bool): Unit {
|
|
427
|
+
// 策略位:窗口过程要在建窗时就拿到它,所以只在 start() 之前调有意义(与 setDragDropPolicy 同规)
|
|
428
|
+
this.ensureHandle()
|
|
429
|
+
var e: Int32 = 0
|
|
430
|
+
if (enabled) {
|
|
431
|
+
e = 1
|
|
432
|
+
}
|
|
433
|
+
unsafe {
|
|
434
|
+
cj_bridge_set_minimize_to_tray(this.handle, e)
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
public func hostCapabilities(): Int32 {
|
|
439
|
+
if (this.handle.isNull()) {
|
|
440
|
+
return 0
|
|
441
|
+
}
|
|
442
|
+
var caps: Int32 = 0
|
|
443
|
+
unsafe {
|
|
444
|
+
caps = cj_bridge_host_capabilities(this.handle)
|
|
445
|
+
}
|
|
446
|
+
return caps
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
public func setShellHandler(handler: (String) -> Unit): Unit {
|
|
450
|
+
this.shellHandler = handler
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
public func setDestroyHandler(handler: () -> Unit): Unit {
|
|
454
|
+
this.onDestroy = handler
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
public func showFileDialog(save: Bool, title: String, filter: String): String {
|
|
458
|
+
return this.showFileDialogPreset(save, title, filter, "")
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
public func showFileDialogPreset(save: Bool, title: String, filter: String,
|
|
462
|
+
defaultName: String): String {
|
|
463
|
+
var kind: Int32 = 0
|
|
464
|
+
if (save) {
|
|
465
|
+
kind = 1
|
|
466
|
+
}
|
|
467
|
+
var ok: Int32 = 0
|
|
468
|
+
unsafe {
|
|
469
|
+
// defaultName 经 message 参数通道交给桥(文件类对话框把它当预置文件名)
|
|
470
|
+
ok = cj_bridge_show_dialog(this.handle, kind, LibC.mallocCString(title),
|
|
471
|
+
LibC.mallocCString(defaultName), LibC.mallocCString(filter))
|
|
472
|
+
}
|
|
473
|
+
if (ok == 0) {
|
|
474
|
+
// 取消 / 宿主未就绪:上游按「空路径」处理,不再读结果位
|
|
475
|
+
return ""
|
|
476
|
+
}
|
|
477
|
+
return this.dialogResult
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
public func showFolderDialog(title: String): String {
|
|
481
|
+
var ok: Int32 = 0
|
|
482
|
+
unsafe {
|
|
483
|
+
// 选目录:kind=6(平台侧走 IFileOpenDialog + FOS_PICKFOLDERS);message 通道不参与
|
|
484
|
+
ok = cj_bridge_show_dialog(this.handle, 6, LibC.mallocCString(title),
|
|
485
|
+
LibC.mallocCString(""), LibC.mallocCString(""))
|
|
486
|
+
}
|
|
487
|
+
if (ok == 0) {
|
|
488
|
+
// 取消 / 宿主未就绪:上游按「空路径」处理
|
|
489
|
+
return ""
|
|
490
|
+
}
|
|
491
|
+
return this.dialogResult
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
public func showMessageDialog(kind: String, title: String, message: String): Bool {
|
|
495
|
+
var ok: Int32 = 0
|
|
496
|
+
unsafe {
|
|
497
|
+
ok = cj_bridge_show_dialog(this.handle, dialogKindCode(kind), LibC.mallocCString(title),
|
|
498
|
+
LibC.mallocCString(message), LibC.mallocCString(""))
|
|
499
|
+
}
|
|
500
|
+
return ok != 0
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
public func clipboardWriteText(text: String): Bool {
|
|
504
|
+
var rc: Int32 = -1
|
|
505
|
+
unsafe {
|
|
506
|
+
rc = cj_bridge_clipboard_write_text(this.handle, LibC.mallocCString(text))
|
|
507
|
+
}
|
|
508
|
+
if (rc != 0) {
|
|
509
|
+
eprintln("[cj-tauri] clipboard write failed: code=${rc}")
|
|
510
|
+
}
|
|
511
|
+
return rc == 0
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
public func clipboardReadText(): Option<String> {
|
|
515
|
+
let cs = unsafe { cj_bridge_clipboard_read_text(this.handle) }
|
|
516
|
+
if (cs.isNull()) {
|
|
517
|
+
return None<String> // 空 / 非文本 / 平台失败,协议层不区分
|
|
518
|
+
}
|
|
519
|
+
let text = cs.toString()
|
|
520
|
+
unsafe {
|
|
521
|
+
cj_bridge_clipboard_free(cs) // 归还缓冲:malloc 家族分配,必须走桥的 free
|
|
522
|
+
}
|
|
523
|
+
return Some(text)
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
public func notify(title: String, body: String): Bool {
|
|
527
|
+
var rc: Int32 = -1
|
|
528
|
+
unsafe {
|
|
529
|
+
rc = cj_bridge_notification_notify(this.handle, LibC.mallocCString(title),
|
|
530
|
+
LibC.mallocCString(body))
|
|
531
|
+
}
|
|
532
|
+
if (rc != 0) {
|
|
533
|
+
// Windows 桩阶段返回 -4(未实现):静态事实,stderr 一行说清,不算异常
|
|
534
|
+
eprintln("[cj-tauri] notification failed: code=${rc}")
|
|
535
|
+
}
|
|
536
|
+
return rc == 0
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
/**
|
|
540
|
+
* 创建宿主编(幂等):首次启动时分配,dispose() 后置空
|
|
541
|
+
*/
|
|
542
|
+
private func ensureHandle(): Unit {
|
|
543
|
+
if (this.handle.isNull()) {
|
|
544
|
+
unsafe {
|
|
545
|
+
this.handle = cj_bridge_create()
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
/**
|
|
551
|
+
* 启动前的共同装配:宿主编、回调槽位、窗口配置、图标
|
|
552
|
+
*/
|
|
553
|
+
private func prepareHost(): Unit {
|
|
554
|
+
this.ensureHandle()
|
|
555
|
+
HostGlobals.onMessage = this.onMessage
|
|
556
|
+
// 宿主级路由:「本句柄 → 本实例的三个回调」登记一条(表式,不覆盖别的窗口)
|
|
557
|
+
HostGlobals.registerHostRoute(this.handle, { json => this.shellHandler(json) },
|
|
558
|
+
{ => this.onDestroy() },
|
|
559
|
+
{ path => this.dialogResult = path })
|
|
560
|
+
// label → 句柄:附庸窗(setOwnerWindow)按 label 找属主窗,登记点与路由表同步
|
|
561
|
+
HostGlobals.registerHostHandle(this.windowLabel, this.handle)
|
|
562
|
+
var devTools: Int32 = 0
|
|
563
|
+
if (this.config.devTools) {
|
|
564
|
+
devTools = 1
|
|
565
|
+
}
|
|
566
|
+
unsafe {
|
|
567
|
+
cj_bridge_init(this.handle, hostOnMessage, hostOnDestroy)
|
|
568
|
+
// shell 事件回调(菜单点击等):与消息回调同一套路,多一个首参用来分辨窗口
|
|
569
|
+
cj_bridge_set_shell_callback(this.handle, shellOnEvent)
|
|
570
|
+
// 原生对话框的结果回调:与消息回调同一套路,多一个首参(结果只落发起这次对话框的窗口)
|
|
571
|
+
cj_bridge_set_dialog_callback(this.handle, dialogOnResult)
|
|
572
|
+
cj_bridge_set_window(this.handle, LibC.mallocCString(this.config.title),
|
|
573
|
+
Int32(this.config.width), Int32(this.config.height))
|
|
574
|
+
cj_bridge_set_devtools(this.handle, devTools)
|
|
575
|
+
// 窗口图标:空串表示系统默认图标
|
|
576
|
+
cj_bridge_set_icon(this.handle, LibC.mallocCString(this.config.iconPath))
|
|
577
|
+
// 预执行脚本(插件 jsShim 等):与 BRIDGE_JS 同一条 document-start 通道,按注册顺序排在桥之后
|
|
578
|
+
for (js in this.initScripts) {
|
|
579
|
+
cj_bridge_add_init_script(this.handle, LibC.mallocCString(js))
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
/**
|
|
585
|
+
* 加载页面(唯一入口,RFC §4.3):Inline/Url/DevServer 直接映射;
|
|
586
|
+
* Asset 经注入的 resolver 读盘,未注入时按 cwd 相对路径读(批次 1 的桌面行为)
|
|
587
|
+
*/
|
|
588
|
+
public func load(source: PageSource): Unit {
|
|
589
|
+
match (resolvePage(source, this.assetResolver)) {
|
|
590
|
+
case StartHtml(html) => this.start(html)
|
|
591
|
+
case StartUrl(url) => this.startUrl(url)
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
/** 注入资产解析器(装配层在 load 前调用) */
|
|
596
|
+
public func setAssetResolver(resolver: Option<AssetResolver>): Unit {
|
|
597
|
+
this.assetResolver = resolver
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
public func start(html: String): Unit {
|
|
601
|
+
this.prepareHost()
|
|
602
|
+
unsafe {
|
|
603
|
+
cj_bridge_start(this.handle, LibC.mallocCString(html))
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
public func startUrl(url: String): Unit {
|
|
608
|
+
this.prepareHost()
|
|
609
|
+
unsafe {
|
|
610
|
+
cj_bridge_load_url(this.handle, LibC.mallocCString(url))
|
|
611
|
+
// 空串表示「页面由 cj_bridge_load_url 指定」(同一次启动里 URL 优先)
|
|
612
|
+
cj_bridge_start(this.handle, LibC.mallocCString(""))
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
public func reload(): Unit {
|
|
617
|
+
unsafe {
|
|
618
|
+
cj_bridge_reload(this.handle)
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
public func runJs(js: String): Unit {
|
|
623
|
+
unsafe {
|
|
624
|
+
cj_bridge_run_js(this.handle, LibC.mallocCString(js))
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
public func quit(): Unit {
|
|
629
|
+
unsafe {
|
|
630
|
+
cj_bridge_quit(this.handle)
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
public func shouldQuit(): Bool {
|
|
635
|
+
unsafe {
|
|
636
|
+
cj_bridge_should_quit(this.handle) != 0
|
|
637
|
+
}
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
/**
|
|
641
|
+
* 释放宿主编(幂等,未创建过则是空操作):事件循环退出后调用一次,之后句柄置空、本实例不可再启动
|
|
642
|
+
*/
|
|
643
|
+
public func dispose(): Unit {
|
|
644
|
+
if (this.handle.isNull()) {
|
|
645
|
+
return
|
|
646
|
+
}
|
|
647
|
+
unsafe {
|
|
648
|
+
cj_bridge_destroy(this.handle)
|
|
649
|
+
}
|
|
650
|
+
this.handle = CPointer<Unit>()
|
|
651
|
+
}
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
// C 回调中转:C 桥线程 → 仓颉闭包(经全局槽位)
|
|
655
|
+
@When[os == "Windows"]
|
|
656
|
+
@C
|
|
657
|
+
func hostOnMessage(json: CString): Unit {
|
|
658
|
+
try {
|
|
659
|
+
HostGlobals.onMessage(json.toString())
|
|
660
|
+
} catch (e: Exception) {
|
|
661
|
+
eprintln("[cj-tauri] host callback error: ${e}")
|
|
662
|
+
}
|
|
663
|
+
}
|