@zogien/native-sdk 0.11.0-fork.4 → 0.11.0-fork.5
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/build/app.zig +50 -34
- package/package.json +9 -9
- package/packages/core/package-lock.json +2 -2
- package/packages/core/package.json +1 -1
- package/skill-data/core/references/bridge-security-native-capabilities.md +4 -0
- package/src/platform/linux/cef_host.cpp +22 -0
- package/src/platform/linux/gtk_host.c +317 -34
- package/src/platform/linux/gtk_host.h +37 -0
- package/src/platform/linux/root.zig +114 -20
- package/src/platform/macos/appkit_host.h +44 -0
- package/src/platform/macos/appkit_host.m +301 -67
- package/src/platform/macos/cef_host.mm +21 -0
- package/src/platform/macos/root.zig +117 -23
- package/src/platform/null_platform.zig +136 -0
- package/src/platform/root.zig +6 -0
- package/src/platform/types.zig +81 -0
- package/src/platform/windows/dialog_test.cpp +303 -0
- package/src/platform/windows/host_loop_test.cpp +169 -0
- package/src/platform/windows/root.zig +225 -39
- package/src/platform/windows/session_end_test.cpp +303 -0
- package/src/platform/windows/webview2_host.cpp +1064 -280
- package/src/root.zig +7 -0
- package/src/runtime/builtin_bridge.zig +108 -13
- package/src/runtime/core.zig +24 -3
- package/src/runtime/dialog_tests.zig +367 -0
- package/src/runtime/dialogs.zig +385 -0
- package/src/runtime/effects.zig +71 -2
- package/src/runtime/effects_host_tests.zig +69 -1
- package/src/runtime/flow.zig +14 -6
- package/src/runtime/flow_reference.zig +14 -6
- package/src/runtime/platform_bridge_tests.zig +1 -0
- package/src/runtime/root.zig +5 -0
- package/src/runtime/system_services.zig +64 -82
- package/src/runtime/ui_app.zig +67 -0
- package/tools/native-sdk/main.zig +1 -1
|
@@ -156,6 +156,38 @@ typedef struct {
|
|
|
156
156
|
size_t tertiary_button_len;
|
|
157
157
|
} native_sdk_gtk_message_dialog_opts_t;
|
|
158
158
|
|
|
159
|
+
enum {
|
|
160
|
+
NATIVE_SDK_GTK_DIALOG_OPEN = 0,
|
|
161
|
+
NATIVE_SDK_GTK_DIALOG_SAVE = 1,
|
|
162
|
+
NATIVE_SDK_GTK_DIALOG_MESSAGE = 2,
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
enum {
|
|
166
|
+
NATIVE_SDK_GTK_DIALOG_SELECTED = 0,
|
|
167
|
+
NATIVE_SDK_GTK_DIALOG_CANCELLED = 1,
|
|
168
|
+
NATIVE_SDK_GTK_DIALOG_FAILED = 2,
|
|
169
|
+
};
|
|
170
|
+
|
|
171
|
+
/* An asynchronous dialog request (native_sdk_gtk_request_dialog): kind
|
|
172
|
+
* picks which of the option pointers is set. */
|
|
173
|
+
typedef struct {
|
|
174
|
+
uint64_t id;
|
|
175
|
+
uint64_t parent_window_id;
|
|
176
|
+
int kind;
|
|
177
|
+
const native_sdk_gtk_open_dialog_opts_t *open_opts;
|
|
178
|
+
const native_sdk_gtk_save_dialog_opts_t *save_opts;
|
|
179
|
+
const native_sdk_gtk_message_dialog_opts_t *message_opts;
|
|
180
|
+
} native_sdk_gtk_dialog_request_t;
|
|
181
|
+
|
|
182
|
+
/* A finished asynchronous dialog; paths are newline-joined. */
|
|
183
|
+
typedef struct {
|
|
184
|
+
uint64_t id;
|
|
185
|
+
int outcome;
|
|
186
|
+
int button;
|
|
187
|
+
size_t count;
|
|
188
|
+
size_t bytes_written;
|
|
189
|
+
} native_sdk_gtk_dialog_result_t;
|
|
190
|
+
|
|
159
191
|
/* resizable/titlebar_style/min_width/min_height mirror the AppKit host's
|
|
160
192
|
* window options: titlebar_style 0 = standard decorations, 1 =
|
|
161
193
|
* hidden_inset, 2 = hidden_inset_tall (the hidden styles create the
|
|
@@ -287,6 +319,11 @@ int native_sdk_gtk_clipboard_write_data(native_sdk_gtk_host_t *host, const char
|
|
|
287
319
|
native_sdk_gtk_open_dialog_result_t native_sdk_gtk_show_open_dialog(native_sdk_gtk_host_t *host, const native_sdk_gtk_open_dialog_opts_t *opts, char *buffer, size_t buffer_len);
|
|
288
320
|
size_t native_sdk_gtk_show_save_dialog(native_sdk_gtk_host_t *host, const native_sdk_gtk_save_dialog_opts_t *opts, char *buffer, size_t buffer_len);
|
|
289
321
|
int native_sdk_gtk_show_message_dialog(native_sdk_gtk_host_t *host, const native_sdk_gtk_message_dialog_opts_t *opts);
|
|
322
|
+
/* Show a dialog without a nested loop: it returns at once, and the
|
|
323
|
+
* result waits for poll after a wake. Returns 0 when nothing was shown. */
|
|
324
|
+
int native_sdk_gtk_request_dialog(native_sdk_gtk_host_t *host, const native_sdk_gtk_dialog_request_t *request);
|
|
325
|
+
void native_sdk_gtk_cancel_dialog(native_sdk_gtk_host_t *host, uint64_t id);
|
|
326
|
+
int native_sdk_gtk_poll_dialog_result(native_sdk_gtk_host_t *host, char *buffer, size_t buffer_len, native_sdk_gtk_dialog_result_t *result);
|
|
290
327
|
|
|
291
328
|
#ifdef __cplusplus
|
|
292
329
|
}
|
|
@@ -234,9 +234,29 @@ const GtkMessageDialogOpts = extern struct {
|
|
|
234
234
|
tertiary_button_len: usize,
|
|
235
235
|
};
|
|
236
236
|
|
|
237
|
+
const GtkDialogRequest = extern struct {
|
|
238
|
+
id: u64,
|
|
239
|
+
parent_window_id: u64,
|
|
240
|
+
kind: c_int,
|
|
241
|
+
open_opts: ?*const GtkOpenDialogOpts,
|
|
242
|
+
save_opts: ?*const GtkSaveDialogOpts,
|
|
243
|
+
message_opts: ?*const GtkMessageDialogOpts,
|
|
244
|
+
};
|
|
245
|
+
|
|
246
|
+
const GtkDialogResult = extern struct {
|
|
247
|
+
id: u64,
|
|
248
|
+
outcome: c_int,
|
|
249
|
+
button: c_int,
|
|
250
|
+
count: usize,
|
|
251
|
+
bytes_written: usize,
|
|
252
|
+
};
|
|
253
|
+
|
|
237
254
|
extern fn native_sdk_gtk_show_open_dialog(host: *GtkHost, opts: *const GtkOpenDialogOpts, buffer: [*]u8, buffer_len: usize) GtkOpenDialogResult;
|
|
238
255
|
extern fn native_sdk_gtk_show_save_dialog(host: *GtkHost, opts: *const GtkSaveDialogOpts, buffer: [*]u8, buffer_len: usize) usize;
|
|
239
256
|
extern fn native_sdk_gtk_show_message_dialog(host: *GtkHost, opts: *const GtkMessageDialogOpts) c_int;
|
|
257
|
+
extern fn native_sdk_gtk_request_dialog(host: *GtkHost, request: *const GtkDialogRequest) c_int;
|
|
258
|
+
extern fn native_sdk_gtk_cancel_dialog(host: *GtkHost, id: u64) void;
|
|
259
|
+
extern fn native_sdk_gtk_poll_dialog_result(host: *GtkHost, buffer: [*]u8, buffer_len: usize, result: *GtkDialogResult) c_int;
|
|
240
260
|
|
|
241
261
|
/// The startup-window twin of the runtime's create-time `.hide` gate:
|
|
242
262
|
/// GTK reports `window_hide_on_close` false (no status item exists to
|
|
@@ -390,6 +410,9 @@ pub const LinuxPlatform = struct {
|
|
|
390
410
|
.show_open_dialog_fn = showOpenDialog,
|
|
391
411
|
.show_save_dialog_fn = showSaveDialog,
|
|
392
412
|
.show_message_dialog_fn = showMessageDialog,
|
|
413
|
+
.request_dialog_fn = if (self.web_engine == .system) requestDialog else null,
|
|
414
|
+
.cancel_dialog_fn = if (self.web_engine == .system) cancelDialog else null,
|
|
415
|
+
.poll_dialog_result_fn = if (self.web_engine == .system) pollDialogResult else null,
|
|
393
416
|
.open_external_url_fn = openExternalUrl,
|
|
394
417
|
.reveal_path_fn = revealPath,
|
|
395
418
|
.show_notification_fn = showNotification,
|
|
@@ -1271,11 +1294,9 @@ fn closeWebView(context: ?*anyopaque, window_id: platform_mod.WindowId, label: [
|
|
|
1271
1294
|
if (native_sdk_gtk_close_webview(self.host, window_id, label.ptr, label.len) == 0) return error.WebViewNotFound;
|
|
1272
1295
|
}
|
|
1273
1296
|
|
|
1274
|
-
fn
|
|
1275
|
-
const
|
|
1276
|
-
|
|
1277
|
-
const ext_str = flattenFilters(options.filters, &ext_buf);
|
|
1278
|
-
const opts = GtkOpenDialogOpts{
|
|
1297
|
+
fn gtkOpenDialogOpts(options: platform_mod.OpenDialogOptions, ext_buf: []u8) GtkOpenDialogOpts {
|
|
1298
|
+
const ext_str = flattenFilters(options.filters, ext_buf);
|
|
1299
|
+
return .{
|
|
1279
1300
|
.title = options.title.ptr,
|
|
1280
1301
|
.title_len = options.title.len,
|
|
1281
1302
|
.default_path = options.default_path.ptr,
|
|
@@ -1285,16 +1306,11 @@ fn showOpenDialog(context: ?*anyopaque, options: platform_mod.OpenDialogOptions,
|
|
|
1285
1306
|
.allow_directories = if (options.allow_directories) 1 else 0,
|
|
1286
1307
|
.allow_multiple = if (options.allow_multiple) 1 else 0,
|
|
1287
1308
|
};
|
|
1288
|
-
const result = native_sdk_gtk_show_open_dialog(self.host, &opts, buffer.ptr, buffer.len);
|
|
1289
|
-
if (result.bytes_written > buffer.len) return error.NoSpaceLeft;
|
|
1290
|
-
return .{ .count = result.count, .paths = buffer[0..result.bytes_written] };
|
|
1291
1309
|
}
|
|
1292
1310
|
|
|
1293
|
-
fn
|
|
1294
|
-
const
|
|
1295
|
-
|
|
1296
|
-
const ext_str = flattenFilters(options.filters, &ext_buf);
|
|
1297
|
-
const opts = GtkSaveDialogOpts{
|
|
1311
|
+
fn gtkSaveDialogOpts(options: platform_mod.SaveDialogOptions, ext_buf: []u8) GtkSaveDialogOpts {
|
|
1312
|
+
const ext_str = flattenFilters(options.filters, ext_buf);
|
|
1313
|
+
return .{
|
|
1298
1314
|
.title = options.title.ptr,
|
|
1299
1315
|
.title_len = options.title.len,
|
|
1300
1316
|
.default_path = options.default_path.ptr,
|
|
@@ -1304,15 +1320,10 @@ fn showSaveDialog(context: ?*anyopaque, options: platform_mod.SaveDialogOptions,
|
|
|
1304
1320
|
.extensions = ext_str.ptr,
|
|
1305
1321
|
.extensions_len = ext_str.len,
|
|
1306
1322
|
};
|
|
1307
|
-
const written = native_sdk_gtk_show_save_dialog(self.host, &opts, buffer.ptr, buffer.len);
|
|
1308
|
-
if (written > buffer.len) return error.NoSpaceLeft;
|
|
1309
|
-
if (written == 0) return null;
|
|
1310
|
-
return buffer[0..written];
|
|
1311
1323
|
}
|
|
1312
1324
|
|
|
1313
|
-
fn
|
|
1314
|
-
|
|
1315
|
-
const opts = GtkMessageDialogOpts{
|
|
1325
|
+
fn gtkMessageDialogOpts(options: platform_mod.MessageDialogOptions) GtkMessageDialogOpts {
|
|
1326
|
+
return .{
|
|
1316
1327
|
.style = @intFromEnum(options.style),
|
|
1317
1328
|
.title = options.title.ptr,
|
|
1318
1329
|
.title_len = options.title.len,
|
|
@@ -1327,9 +1338,92 @@ fn showMessageDialog(context: ?*anyopaque, options: platform_mod.MessageDialogOp
|
|
|
1327
1338
|
.tertiary_button = options.tertiary_button.ptr,
|
|
1328
1339
|
.tertiary_button_len = options.tertiary_button.len,
|
|
1329
1340
|
};
|
|
1341
|
+
}
|
|
1342
|
+
|
|
1343
|
+
fn showOpenDialog(context: ?*anyopaque, options: platform_mod.OpenDialogOptions, buffer: []u8) anyerror!platform_mod.OpenDialogResult {
|
|
1344
|
+
const self: *LinuxPlatform = @ptrCast(@alignCast(context.?));
|
|
1345
|
+
var ext_buf: [1024]u8 = undefined;
|
|
1346
|
+
const opts = gtkOpenDialogOpts(options, &ext_buf);
|
|
1347
|
+
const result = native_sdk_gtk_show_open_dialog(self.host, &opts, buffer.ptr, buffer.len);
|
|
1348
|
+
if (result.bytes_written > buffer.len) return error.NoSpaceLeft;
|
|
1349
|
+
return .{ .count = result.count, .paths = buffer[0..result.bytes_written] };
|
|
1350
|
+
}
|
|
1351
|
+
|
|
1352
|
+
fn showSaveDialog(context: ?*anyopaque, options: platform_mod.SaveDialogOptions, buffer: []u8) anyerror!?[]const u8 {
|
|
1353
|
+
const self: *LinuxPlatform = @ptrCast(@alignCast(context.?));
|
|
1354
|
+
var ext_buf: [1024]u8 = undefined;
|
|
1355
|
+
const opts = gtkSaveDialogOpts(options, &ext_buf);
|
|
1356
|
+
const written = native_sdk_gtk_show_save_dialog(self.host, &opts, buffer.ptr, buffer.len);
|
|
1357
|
+
if (written > buffer.len) return error.NoSpaceLeft;
|
|
1358
|
+
if (written == 0) return null;
|
|
1359
|
+
return buffer[0..written];
|
|
1360
|
+
}
|
|
1361
|
+
|
|
1362
|
+
fn showMessageDialog(context: ?*anyopaque, options: platform_mod.MessageDialogOptions) anyerror!platform_mod.MessageDialogResult {
|
|
1363
|
+
const self: *LinuxPlatform = @ptrCast(@alignCast(context.?));
|
|
1364
|
+
const opts = gtkMessageDialogOpts(options);
|
|
1330
1365
|
return @enumFromInt(native_sdk_gtk_show_message_dialog(self.host, &opts));
|
|
1331
1366
|
}
|
|
1332
1367
|
|
|
1368
|
+
// The host copies every option before returning, so they may live on this
|
|
1369
|
+
// stack; the result comes back through pollDialogResult on a later wake.
|
|
1370
|
+
fn requestDialog(context: ?*anyopaque, request: platform_mod.DialogRequest) anyerror!void {
|
|
1371
|
+
const self: *LinuxPlatform = @ptrCast(@alignCast(context.?));
|
|
1372
|
+
var ext_buf: [1024]u8 = undefined;
|
|
1373
|
+
var open_opts: GtkOpenDialogOpts = undefined;
|
|
1374
|
+
var save_opts: GtkSaveDialogOpts = undefined;
|
|
1375
|
+
var message_opts: GtkMessageDialogOpts = undefined;
|
|
1376
|
+
var native_request = GtkDialogRequest{
|
|
1377
|
+
.id = request.id,
|
|
1378
|
+
.parent_window_id = request.parent_window_id orelse 0,
|
|
1379
|
+
.kind = @intFromEnum(std.meta.activeTag(request.options)),
|
|
1380
|
+
.open_opts = null,
|
|
1381
|
+
.save_opts = null,
|
|
1382
|
+
.message_opts = null,
|
|
1383
|
+
};
|
|
1384
|
+
switch (request.options) {
|
|
1385
|
+
.open => |options| {
|
|
1386
|
+
open_opts = gtkOpenDialogOpts(options, &ext_buf);
|
|
1387
|
+
native_request.open_opts = &open_opts;
|
|
1388
|
+
},
|
|
1389
|
+
.save => |options| {
|
|
1390
|
+
save_opts = gtkSaveDialogOpts(options, &ext_buf);
|
|
1391
|
+
native_request.save_opts = &save_opts;
|
|
1392
|
+
},
|
|
1393
|
+
.message => |options| {
|
|
1394
|
+
message_opts = gtkMessageDialogOpts(options);
|
|
1395
|
+
native_request.message_opts = &message_opts;
|
|
1396
|
+
},
|
|
1397
|
+
}
|
|
1398
|
+
if (native_sdk_gtk_request_dialog(self.host, &native_request) == 0) return error.DialogUnavailable;
|
|
1399
|
+
}
|
|
1400
|
+
|
|
1401
|
+
fn cancelDialog(context: ?*anyopaque, id: platform_mod.DialogRequestId) void {
|
|
1402
|
+
const self: *LinuxPlatform = @ptrCast(@alignCast(context.?));
|
|
1403
|
+
native_sdk_gtk_cancel_dialog(self.host, id);
|
|
1404
|
+
}
|
|
1405
|
+
|
|
1406
|
+
fn pollDialogResult(context: ?*anyopaque, buffer: []u8) ?platform_mod.DialogResult {
|
|
1407
|
+
const self: *LinuxPlatform = @ptrCast(@alignCast(context.?));
|
|
1408
|
+
var result: GtkDialogResult = undefined;
|
|
1409
|
+
if (native_sdk_gtk_poll_dialog_result(self.host, buffer.ptr, buffer.len, &result) == 0) return null;
|
|
1410
|
+
return .{
|
|
1411
|
+
.id = result.id,
|
|
1412
|
+
.outcome = switch (result.outcome) {
|
|
1413
|
+
0 => .selected,
|
|
1414
|
+
1 => .cancelled,
|
|
1415
|
+
else => .failed,
|
|
1416
|
+
},
|
|
1417
|
+
.paths = buffer[0..@min(result.bytes_written, buffer.len)],
|
|
1418
|
+
.count = result.count,
|
|
1419
|
+
.button = switch (result.button) {
|
|
1420
|
+
1 => .secondary,
|
|
1421
|
+
2 => .tertiary,
|
|
1422
|
+
else => .primary,
|
|
1423
|
+
},
|
|
1424
|
+
};
|
|
1425
|
+
}
|
|
1426
|
+
|
|
1333
1427
|
fn openExternalUrl(context: ?*anyopaque, url: []const u8) anyerror!void {
|
|
1334
1428
|
const self: *LinuxPlatform = @ptrCast(@alignCast(context.?));
|
|
1335
1429
|
if (self.web_engine != .system) return error.UnsupportedService;
|
|
@@ -844,6 +844,50 @@ int native_sdk_appkit_show_context_menu(native_sdk_appkit_host_t *host, uint64_t
|
|
|
844
844
|
native_sdk_appkit_open_dialog_result_t native_sdk_appkit_show_open_dialog(native_sdk_appkit_host_t *host, const native_sdk_appkit_open_dialog_opts_t *opts, char *buffer, size_t buffer_len);
|
|
845
845
|
size_t native_sdk_appkit_show_save_dialog(native_sdk_appkit_host_t *host, const native_sdk_appkit_save_dialog_opts_t *opts, char *buffer, size_t buffer_len);
|
|
846
846
|
int native_sdk_appkit_show_message_dialog(native_sdk_appkit_host_t *host, const native_sdk_appkit_message_dialog_opts_t *opts);
|
|
847
|
+
|
|
848
|
+
/* Asynchronous dialogs. A request returns at once: with a visible parent
|
|
849
|
+
* window the dialog is a sheet on it, otherwise a modeless panel (or, for
|
|
850
|
+
* a message without any window, a modal alert started on the next loop
|
|
851
|
+
* turn). When a dialog finishes the host keeps its result and posts a
|
|
852
|
+
* wake; poll drains finished dialogs one at a time. Cancelling closes a
|
|
853
|
+
* presented dialog, which then finishes as cancelled. */
|
|
854
|
+
enum {
|
|
855
|
+
NATIVE_SDK_APPKIT_DIALOG_OPEN = 0,
|
|
856
|
+
NATIVE_SDK_APPKIT_DIALOG_SAVE = 1,
|
|
857
|
+
NATIVE_SDK_APPKIT_DIALOG_MESSAGE = 2,
|
|
858
|
+
};
|
|
859
|
+
|
|
860
|
+
enum {
|
|
861
|
+
NATIVE_SDK_APPKIT_DIALOG_SELECTED = 0,
|
|
862
|
+
NATIVE_SDK_APPKIT_DIALOG_CANCELLED = 1,
|
|
863
|
+
NATIVE_SDK_APPKIT_DIALOG_FAILED = 2,
|
|
864
|
+
};
|
|
865
|
+
|
|
866
|
+
typedef struct {
|
|
867
|
+
uint64_t id;
|
|
868
|
+
/* 0 presents without a parent. */
|
|
869
|
+
uint64_t parent_window_id;
|
|
870
|
+
int kind;
|
|
871
|
+
const native_sdk_appkit_open_dialog_opts_t *open_opts;
|
|
872
|
+
const native_sdk_appkit_save_dialog_opts_t *save_opts;
|
|
873
|
+
const native_sdk_appkit_message_dialog_opts_t *message_opts;
|
|
874
|
+
} native_sdk_appkit_dialog_request_t;
|
|
875
|
+
|
|
876
|
+
typedef struct {
|
|
877
|
+
uint64_t id;
|
|
878
|
+
int outcome;
|
|
879
|
+
/* Message dialogs: 0 primary, 1 secondary, 2 tertiary. */
|
|
880
|
+
int button;
|
|
881
|
+
size_t count;
|
|
882
|
+
size_t bytes_written;
|
|
883
|
+
} native_sdk_appkit_dialog_result_t;
|
|
884
|
+
|
|
885
|
+
/* 1 when the dialog was accepted for presentation, 0 otherwise. */
|
|
886
|
+
int native_sdk_appkit_request_dialog(native_sdk_appkit_host_t *host, const native_sdk_appkit_dialog_request_t *request);
|
|
887
|
+
void native_sdk_appkit_cancel_dialog(native_sdk_appkit_host_t *host, uint64_t id);
|
|
888
|
+
/* 1 when a finished dialog was written to result (its newline-separated
|
|
889
|
+
* paths into buffer), 0 when none is waiting. */
|
|
890
|
+
int native_sdk_appkit_poll_dialog_result(native_sdk_appkit_host_t *host, char *buffer, size_t buffer_len, native_sdk_appkit_dialog_result_t *result);
|
|
847
891
|
void native_sdk_appkit_create_tray(native_sdk_appkit_host_t *host, uint32_t status_item_id, const char *icon_path, size_t icon_path_len, const char *title, size_t title_len, const char *tooltip, size_t tooltip_len, int visible, double width, int tone, double icon_opacity, int monospaced, double font_size, int font_weight, const char *activation_command, size_t activation_command_len, const char *alternate_activation_command, size_t alternate_activation_command_len, const char *open_command, size_t open_command_len);
|
|
848
892
|
void native_sdk_appkit_update_tray_shell(native_sdk_appkit_host_t *host, uint32_t status_item_id, const char *icon_path, size_t icon_path_len, const char *tooltip, size_t tooltip_len, int visible, const char *activation_command, size_t activation_command_len, const char *alternate_activation_command, size_t alternate_activation_command_len, const char *open_command, size_t open_command_len);
|
|
849
893
|
void native_sdk_appkit_update_tray_menu(native_sdk_appkit_host_t *host, uint32_t status_item_id, const uint32_t *item_ids, const char *const *labels, const size_t *label_lens, const int *separators, const int *enabled_flags, const char *const *details, const size_t *detail_lens, const int *roles, const char *const *keys, const size_t *key_lens, const uint32_t *modifiers, size_t count);
|