electrobun 1.18.1 → 1.18.4-beta.10

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 (64) hide show
  1. package/README.md +37 -14
  2. package/dash.config.ts +28 -0
  3. package/dist/api/browser/global.d.ts +6 -0
  4. package/dist/api/browser/index.ts +162 -44
  5. package/dist/api/{bun → config}/ElectrobunConfig.ts +109 -40
  6. package/dist/api/config/validate.test.ts +31 -0
  7. package/dist/api/config/validate.ts +19 -0
  8. package/dist/api/preload/.generated/compiled.ts +8 -0
  9. package/dist/api/{bun/preload → preload}/build.ts +6 -6
  10. package/dist/api/{bun/preload → preload}/encryption.ts +11 -5
  11. package/dist/api/{bun/preload → preload}/globals.d.ts +8 -0
  12. package/dist/api/{bun/preload → preload}/index.ts +18 -8
  13. package/dist/api/{bun/preload → preload}/webviewTag.ts +32 -3
  14. package/dist/api/{bun/preload → preload}/wgpuTag.ts +33 -2
  15. package/dist/api/{bun → sdks/bun}/__tests__/ffi-contract.test.ts +6 -9
  16. package/dist/api/{bun → sdks/bun}/core/BrowserView.ts +96 -55
  17. package/dist/api/{bun → sdks/bun}/core/BrowserWindow.ts +20 -30
  18. package/dist/api/{bun → sdks/bun}/core/BuildConfig.ts +32 -5
  19. package/dist/api/{bun → sdks/bun}/core/GpuWindow.ts +20 -7
  20. package/dist/api/sdks/bun/core/Socket.ts +22 -0
  21. package/dist/api/{bun → sdks/bun}/core/Tray.ts +33 -32
  22. package/dist/api/{bun → sdks/bun}/core/Updater.ts +10 -10
  23. package/dist/api/{bun → sdks/bun}/core/Utils.ts +3 -5
  24. package/dist/api/{bun → sdks/bun}/core/WGPUView.ts +43 -13
  25. package/dist/api/{bun → sdks/bun}/index.ts +39 -10
  26. package/dist/api/{bun → sdks/bun}/proc/native.ts +942 -746
  27. package/dist/api/{bun → sdks/bun}/webGPU.ts +1 -1
  28. package/dist/api/{bun → sdks/bun}/webgpuAdapter.ts +40 -33
  29. package/dist/api/shared/build-dependencies.test.ts +48 -0
  30. package/dist/api/shared/build-dependencies.ts +46 -0
  31. package/dist/api/shared/go-version.ts +3 -0
  32. package/dist/api/shared/odin-version.ts +6 -0
  33. package/dist/api/shared/rust-version.ts +3 -0
  34. package/dist/go-sdk/callbacks.go +260 -0
  35. package/dist/go-sdk/electrobun.go +2021 -0
  36. package/dist/main.js +35 -28
  37. package/dist/odin-sdk/electrobun/electrobun.odin +2337 -0
  38. package/dist/preload-full.js +948 -0
  39. package/dist/preload-sandboxed.js +111 -0
  40. package/dist/rust-sdk/electrobun.rs +2396 -0
  41. package/dist/zig-sdk/electrobun.zig +2005 -0
  42. package/package.json +5 -29
  43. package/src/cli/index.ts +868 -654
  44. package/bin/electrobun.cjs +0 -169
  45. package/dist/api/bun/core/Socket.ts +0 -205
  46. package/dist/api/bun/core/windowIds.ts +0 -5
  47. package/dist/api/bun/preload/.generated/compiled.ts +0 -8
  48. package/dist/api/shared/bun-version.ts +0 -3
  49. /package/dist/api/{bun/preload → preload}/dragRegions.ts +0 -0
  50. /package/dist/api/{bun/preload → preload}/events.ts +0 -0
  51. /package/dist/api/{bun/preload → preload}/index-sandboxed.ts +0 -0
  52. /package/dist/api/{bun/preload → preload}/internalRpc.ts +0 -0
  53. /package/dist/api/{bun/preload → preload}/overlaySync.ts +0 -0
  54. /package/dist/api/{bun → sdks/bun}/core/ApplicationMenu.ts +0 -0
  55. /package/dist/api/{bun → sdks/bun}/core/ContextMenu.ts +0 -0
  56. /package/dist/api/{bun → sdks/bun}/core/Paths.ts +0 -0
  57. /package/dist/api/{bun → sdks/bun}/core/menuRoles.ts +0 -0
  58. /package/dist/api/{bun → sdks/bun}/events/ApplicationEvents.ts +0 -0
  59. /package/dist/api/{bun → sdks/bun}/events/event.ts +0 -0
  60. /package/dist/api/{bun → sdks/bun}/events/eventEmitter.ts +0 -0
  61. /package/dist/api/{bun → sdks/bun}/events/trayEvents.ts +0 -0
  62. /package/dist/api/{bun → sdks/bun}/events/webviewEvents.ts +0 -0
  63. /package/dist/api/{bun → sdks/bun}/events/windowEvents.ts +0 -0
  64. /package/dist/api/{bun → sdks/bun}/proc/linux.md +0 -0
@@ -291,7 +291,7 @@ const WGPU_LIB_NAMES: Record<string, string[]> = {
291
291
  };
292
292
 
293
293
  function findWgpuLibraryPath(): string | null {
294
- const envPath = process.env['ELECTROBUN_WGPU_PATH'];
294
+ const envPath = process.env["ELECTROBUN_WGPU_PATH"];
295
295
  if (envPath && existsSync(envPath)) return envPath;
296
296
 
297
297
  const names = WGPU_LIB_NAMES[process.platform] ?? ["libwebgpu_dawn." + suffix];
@@ -3,7 +3,7 @@ import { WGPUView } from "./core/WGPUView";
3
3
  import { GpuWindow } from "./core/GpuWindow";
4
4
  import WGPU from "./webGPU";
5
5
  import { WGPUBridge } from "./proc/native";
6
- import { ptr, CString, toArrayBuffer, type Pointer, JSCallback } from "bun:ffi";
6
+ import { ptr, toArrayBuffer, type Pointer, JSCallback } from "bun:ffi";
7
7
  import { inflateSync } from "zlib";
8
8
 
9
9
  const WGPUNative = WGPU.native;
@@ -223,9 +223,13 @@ function makeStringView(str?: string | null) {
223
223
  if (!str) {
224
224
  return { ptr: 0, len: 0n, cstr: null };
225
225
  }
226
- const cstr = new CString(str);
227
- WGPU_KEEPALIVE.push(cstr);
228
- return { ptr: cstr.ptr, len: WGPU_STRLEN, cstr };
226
+ const bytes = new TextEncoder().encode(str);
227
+ WGPU_KEEPALIVE.push(bytes);
228
+ return { ptr: ptr(bytes), len: BigInt(bytes.byteLength), cstr: bytes };
229
+ }
230
+
231
+ function ptrOrNull(value: ArrayBuffer | ArrayBufferView) {
232
+ return value.byteLength === 0 ? 0 : ptr(value);
229
233
  }
230
234
 
231
235
  function makeSurfaceConfiguration(
@@ -935,7 +939,7 @@ class GPUQueue {
935
939
  WGPUNative.symbols.wgpuQueueSubmit(
936
940
  this.ptr,
937
941
  BigInt(commandBuffers.length) as any,
938
- ptr(buffer),
942
+ ptrOrNull(buffer),
939
943
  );
940
944
  if (LAST_SURFACE_PTR && LAST_SURFACE_HAS_TEXTURE) {
941
945
  LAST_SURFACE_HAS_TEXTURE = false;
@@ -947,7 +951,7 @@ class GPUQueue {
947
951
  this.ptr,
948
952
  buffer.ptr,
949
953
  BigInt(offset),
950
- ptr(data),
954
+ ptrOrNull(data),
951
955
  data.byteLength,
952
956
  );
953
957
  }
@@ -1271,7 +1275,7 @@ class GPUDevice {
1271
1275
  new Uint8Array(entry.buffer),
1272
1276
  );
1273
1277
  });
1274
- const entryPtr = ptr(entryBuf);
1278
+ const entryPtr = ptrOrNull(entryBuf);
1275
1279
  WGPU_KEEPALIVE.push(entryBuf);
1276
1280
  const desc = makeBindGroupLayoutDescriptor(
1277
1281
  entryPtr as any,
@@ -1286,39 +1290,39 @@ class GPUDevice {
1286
1290
  }
1287
1291
  createBindGroup(descriptor: { layout: GPUBindGroupLayout; entries: any[] }) {
1288
1292
  const entries = descriptor.entries.map((entry) => {
1289
- if (entry.resource?.buffer || entry.resource instanceof GPUBuffer) {
1290
- const buffer = entry.resource.buffer ?? entry.resource;
1293
+ const bufferResource =
1294
+ entry.resource?.buffer || entry.resource instanceof GPUBuffer
1295
+ ? entry.resource
1296
+ : entry.buffer;
1297
+ if (bufferResource) {
1298
+ const buffer = bufferResource.buffer ?? bufferResource;
1291
1299
  return makeBindGroupEntry({
1292
1300
  binding: entry.binding ?? 0,
1293
1301
  buffer: {
1294
1302
  buffer,
1295
- offset: entry.resource.offset ?? 0,
1296
- size: entry.resource.size ?? 0xffffffffffffffffn,
1303
+ offset: bufferResource.offset ?? 0,
1304
+ size: bufferResource.size ?? 0xffffffffffffffffn,
1297
1305
  },
1298
1306
  });
1299
1307
  }
1300
- if (entry.resource instanceof GPUSampler) {
1301
- return makeBindGroupEntry({
1302
- binding: entry.binding ?? 0,
1303
- sampler: entry.resource,
1304
- });
1305
- }
1306
- if (entry.resource instanceof GPUTextureView) {
1308
+ const sampler =
1309
+ entry.resource instanceof GPUSampler
1310
+ ? entry.resource
1311
+ : entry.resource?.sampler ?? entry.sampler;
1312
+ if (sampler) {
1307
1313
  return makeBindGroupEntry({
1308
1314
  binding: entry.binding ?? 0,
1309
- textureView: entry.resource,
1315
+ sampler,
1310
1316
  });
1311
1317
  }
1312
- if (entry.resource?.sampler) {
1318
+ const textureView =
1319
+ entry.resource instanceof GPUTextureView
1320
+ ? entry.resource
1321
+ : entry.resource?.textureView ?? entry.textureView;
1322
+ if (textureView) {
1313
1323
  return makeBindGroupEntry({
1314
1324
  binding: entry.binding ?? 0,
1315
- sampler: entry.resource.sampler,
1316
- });
1317
- }
1318
- if (entry.resource?.textureView) {
1319
- return makeBindGroupEntry({
1320
- binding: entry.binding ?? 0,
1321
- textureView: entry.resource.textureView,
1325
+ textureView,
1322
1326
  });
1323
1327
  }
1324
1328
  return makeBindGroupEntry({ binding: entry.binding ?? 0 });
@@ -1329,7 +1333,7 @@ class GPUDevice {
1329
1333
  new Uint8Array(entry.buffer),
1330
1334
  );
1331
1335
  });
1332
- const entryPtr = ptr(entryBuf);
1336
+ const entryPtr = ptrOrNull(entryBuf);
1333
1337
  WGPU_KEEPALIVE.push(entryBuf);
1334
1338
  const desc = makeBindGroupDescriptor(
1335
1339
  descriptor.layout.ptr,
@@ -1349,7 +1353,10 @@ class GPUDevice {
1349
1353
  layouts[i] = BigInt(descriptor.bindGroupLayouts[i]!.ptr);
1350
1354
  }
1351
1355
  WGPU_KEEPALIVE.push(layouts);
1352
- const desc = makePipelineLayoutDescriptor(ptr(layouts) as any, layouts.length);
1356
+ const desc = makePipelineLayoutDescriptor(
1357
+ ptrOrNull(layouts) as any,
1358
+ layouts.length,
1359
+ );
1353
1360
  WGPU_KEEPALIVE.push(desc.buffer);
1354
1361
  const layoutPtr = WGPUNative.symbols.wgpuDeviceCreatePipelineLayout(
1355
1362
  this.ptr,
@@ -1391,7 +1398,7 @@ class GPUDevice {
1391
1398
  new Uint8Array(attrStruct.buffer),
1392
1399
  );
1393
1400
  });
1394
- const attrPtr = ptr(attrBuf);
1401
+ const attrPtr = ptrOrNull(attrBuf);
1395
1402
  WGPU_KEEPALIVE.push(attrBuf);
1396
1403
  const layout = makeVertexBufferLayout(
1397
1404
  attrPtr as any,
@@ -1410,7 +1417,7 @@ class GPUDevice {
1410
1417
  new Uint8Array(layoutBuf),
1411
1418
  );
1412
1419
  });
1413
- const vertexLayoutsPtr = ptr(vertexLayoutsBuf);
1420
+ const vertexLayoutsPtr = ptrOrNull(vertexLayoutsBuf);
1414
1421
  WGPU_KEEPALIVE.push(vertexLayoutsBuf);
1415
1422
 
1416
1423
  const vertexState = makeVertexState(
@@ -1453,7 +1460,7 @@ class GPUDevice {
1453
1460
  new Uint8Array(target.buffer),
1454
1461
  );
1455
1462
  });
1456
- const targetPtr = ptr(targetBuf);
1463
+ const targetPtr = ptrOrNull(targetBuf);
1457
1464
  WGPU_KEEPALIVE.push(targetBuf);
1458
1465
  const fragState = makeFragmentState(
1459
1466
  fragModule.ptr,
@@ -1831,7 +1838,7 @@ class GPUCommandEncoder {
1831
1838
  colorAttachments.forEach((c, i) => {
1832
1839
  new Uint8Array(colorBuf, i * 72, 72).set(new Uint8Array(c.buffer));
1833
1840
  });
1834
- const colorPtr = ptr(colorBuf);
1841
+ const colorPtr = ptrOrNull(colorBuf);
1835
1842
  WGPU_KEEPALIVE.push(colorBuf);
1836
1843
 
1837
1844
  let depthPtr: number | null = null;
@@ -0,0 +1,48 @@
1
+ import { describe, expect, test } from "bun:test";
2
+ import {
3
+ BUILD_DEPENDENCIES_PUBLIC_BASE_URL,
4
+ OWNED_BUILD_DEPENDENCY_VERSIONS,
5
+ ownedBuildDependencyArtifact,
6
+ } from "./build-dependencies";
7
+
8
+ describe("owned build dependency artifacts", () => {
9
+ test.each([
10
+ ["zig-bsdiff", "macos", "arm64", "zig-bsdiff-darwin-arm64.tar.gz"],
11
+ ["zig-zstd", "linux", "x64", "zig-zstd-linux-x64.tar.gz"],
12
+ ["zig-asar", "win", "x64", "zig-asar-win32-x64.tar.gz"],
13
+ [
14
+ "electrobun-dawn",
15
+ "linux",
16
+ "arm64",
17
+ "electrobun-dawn-linux-arm64.tar.gz",
18
+ ],
19
+ ] as const)(
20
+ "maps %s on %s-%s to its immutable release key",
21
+ (product, platform, arch, filename) => {
22
+ const artifact = ownedBuildDependencyArtifact(product, platform, arch);
23
+ const version = OWNED_BUILD_DEPENDENCY_VERSIONS[product];
24
+
25
+ expect(artifact.filename).toBe(filename);
26
+ expect(artifact.key).toBe(
27
+ `${product}/releases/${version}/${filename}`,
28
+ );
29
+ expect(artifact.url).toBe(
30
+ `${BUILD_DEPENDENCIES_PUBLIC_BASE_URL}/${artifact.key}`,
31
+ );
32
+ expect(artifact.checksumUrl).toBe(`${artifact.url}.sha256`);
33
+ },
34
+ );
35
+
36
+ test("normalizes an overridden public base URL", () => {
37
+ const artifact = ownedBuildDependencyArtifact(
38
+ "zig-bsdiff",
39
+ "linux",
40
+ "x64",
41
+ "https://artifacts.example.test///",
42
+ );
43
+
44
+ expect(artifact.url).toBe(
45
+ "https://artifacts.example.test/zig-bsdiff/releases/0.1.21/zig-bsdiff-linux-x64.tar.gz",
46
+ );
47
+ });
48
+ });
@@ -0,0 +1,46 @@
1
+ export const BUILD_DEPENDENCIES_PUBLIC_BASE_URL =
2
+ "https://electrobun-artifacts.blackboard.sh";
3
+
4
+ export const ZIG_VERSION = "0.13.0";
5
+
6
+ export const OWNED_BUILD_DEPENDENCY_VERSIONS = {
7
+ "zig-bsdiff": "0.1.21",
8
+ "zig-zstd": "0.1.4",
9
+ "zig-asar": "0.2.3",
10
+ "electrobun-dawn": "0.2.5",
11
+ } as const;
12
+
13
+ export type OwnedBuildDependency =
14
+ keyof typeof OWNED_BUILD_DEPENDENCY_VERSIONS;
15
+
16
+ export type BuildDependencyPlatform = "macos" | "linux" | "win";
17
+ export type BuildDependencyArch = "arm64" | "x64";
18
+
19
+ const artifactPlatform = (
20
+ platform: BuildDependencyPlatform,
21
+ ): "darwin" | "linux" | "win32" => {
22
+ if (platform === "macos") return "darwin";
23
+ if (platform === "win") return "win32";
24
+ return "linux";
25
+ };
26
+
27
+ export const ownedBuildDependencyArtifact = (
28
+ product: OwnedBuildDependency,
29
+ platform: BuildDependencyPlatform,
30
+ arch: BuildDependencyArch,
31
+ publicBaseUrl = BUILD_DEPENDENCIES_PUBLIC_BASE_URL,
32
+ ) => {
33
+ const version = OWNED_BUILD_DEPENDENCY_VERSIONS[product];
34
+ const filename = `${product}-${artifactPlatform(platform)}-${arch}.tar.gz`;
35
+ const key = `${product}/releases/${version}/${filename}`;
36
+ const baseUrl = publicBaseUrl.replace(/\/+$/, "");
37
+
38
+ return {
39
+ product,
40
+ version,
41
+ filename,
42
+ key,
43
+ url: `${baseUrl}/${key}`,
44
+ checksumUrl: `${baseUrl}/${key}.sha256`,
45
+ };
46
+ };
@@ -0,0 +1,3 @@
1
+ // Default Go toolchain version used to compile Go main processes.
2
+ // This is vendored by package/build.ts; Electrobun must not use a system Go.
3
+ export const GO_VERSION = "1.26.4";
@@ -0,0 +1,6 @@
1
+ // Default Odin toolchain release used to compile Odin main processes.
2
+ // This is vendored by package/build.ts; Electrobun must not use a system Odin.
3
+ // Odin is pre-1.0 and ships monthly "dev-YYYY-MM" releases that can contain
4
+ // breaking changes, so this must stay pinned to a release the SDK is known
5
+ // to compile with.
6
+ export const ODIN_VERSION = "dev-2026-07a";
@@ -0,0 +1,3 @@
1
+ // Default Rust toolchain version used to compile Rust main processes.
2
+ // This is vendored by package/build.ts; Electrobun must not use a system Rust.
3
+ export const RUST_VERSION = "1.88.0";
@@ -0,0 +1,260 @@
1
+ package electrobun
2
+
3
+ /*
4
+ #include <stdint.h>
5
+ */
6
+ import "C"
7
+
8
+ import "sync"
9
+
10
+ var callbackMu sync.RWMutex
11
+
12
+ var windowCallbackRegistry = map[uint32]WindowCallbacks{}
13
+ var webviewCallbackRegistry = map[uint32]WebviewCallbacks{}
14
+
15
+ var statusItemHandler StatusItemHandler
16
+ var globalShortcutHandler func(string)
17
+ var urlOpenHandler func(string)
18
+ var appReopenHandler func()
19
+ var quitRequestedHandler func()
20
+
21
+ func registerWindowCallbacks(windowID uint32, callbacks WindowCallbacks) {
22
+ if callbacks.Close == nil &&
23
+ callbacks.Move == nil &&
24
+ callbacks.Resize == nil &&
25
+ callbacks.Focus == nil &&
26
+ callbacks.Blur == nil &&
27
+ callbacks.Key == nil {
28
+ return
29
+ }
30
+ callbackMu.Lock()
31
+ windowCallbackRegistry[windowID] = callbacks
32
+ callbackMu.Unlock()
33
+ }
34
+
35
+ func forgetWindowCallbacks(windowID uint32) {
36
+ callbackMu.Lock()
37
+ delete(windowCallbackRegistry, windowID)
38
+ callbackMu.Unlock()
39
+ }
40
+
41
+ func registerWebviewCallbacks(webviewID uint32, callbacks WebviewCallbacks) {
42
+ if callbacks.DecideNavigation == nil &&
43
+ callbacks.Event == nil &&
44
+ callbacks.EventBridge == nil &&
45
+ callbacks.HostBridge == nil &&
46
+ callbacks.InternalBridge == nil {
47
+ return
48
+ }
49
+ callbackMu.Lock()
50
+ webviewCallbackRegistry[webviewID] = callbacks
51
+ callbackMu.Unlock()
52
+ }
53
+
54
+ func forgetWebviewCallbacks(webviewID uint32) {
55
+ callbackMu.Lock()
56
+ delete(webviewCallbackRegistry, webviewID)
57
+ callbackMu.Unlock()
58
+ }
59
+
60
+ func setStatusItemHandler(handler StatusItemHandler) {
61
+ callbackMu.Lock()
62
+ statusItemHandler = handler
63
+ callbackMu.Unlock()
64
+ }
65
+
66
+ func setGlobalShortcutHandler(handler func(string)) {
67
+ callbackMu.Lock()
68
+ globalShortcutHandler = handler
69
+ callbackMu.Unlock()
70
+ }
71
+
72
+ func setURLOpenHandler(handler func(string)) {
73
+ callbackMu.Lock()
74
+ urlOpenHandler = handler
75
+ callbackMu.Unlock()
76
+ }
77
+
78
+ func setAppReopenHandler(handler func()) {
79
+ callbackMu.Lock()
80
+ appReopenHandler = handler
81
+ callbackMu.Unlock()
82
+ }
83
+
84
+ func setQuitRequestedHandler(handler func()) {
85
+ callbackMu.Lock()
86
+ quitRequestedHandler = handler
87
+ callbackMu.Unlock()
88
+ }
89
+
90
+ //export electrobunWindowCloseHandler
91
+ func electrobunWindowCloseHandler(windowID C.uint32_t) {
92
+ id := uint32(windowID)
93
+ callbackMu.RLock()
94
+ handler := windowCallbackRegistry[id].Close
95
+ callbackMu.RUnlock()
96
+ if handler != nil {
97
+ handler(id)
98
+ }
99
+ }
100
+
101
+ //export electrobunWindowMoveHandler
102
+ func electrobunWindowMoveHandler(windowID C.uint32_t, x C.double, y C.double) {
103
+ id := uint32(windowID)
104
+ callbackMu.RLock()
105
+ handler := windowCallbackRegistry[id].Move
106
+ callbackMu.RUnlock()
107
+ if handler != nil {
108
+ handler(id, float64(x), float64(y))
109
+ }
110
+ }
111
+
112
+ //export electrobunWindowResizeHandler
113
+ func electrobunWindowResizeHandler(windowID C.uint32_t, x C.double, y C.double, width C.double, height C.double) {
114
+ id := uint32(windowID)
115
+ callbackMu.RLock()
116
+ handler := windowCallbackRegistry[id].Resize
117
+ callbackMu.RUnlock()
118
+ if handler != nil {
119
+ handler(id, float64(x), float64(y), float64(width), float64(height))
120
+ }
121
+ }
122
+
123
+ //export electrobunWindowFocusHandler
124
+ func electrobunWindowFocusHandler(windowID C.uint32_t) {
125
+ id := uint32(windowID)
126
+ callbackMu.RLock()
127
+ handler := windowCallbackRegistry[id].Focus
128
+ callbackMu.RUnlock()
129
+ if handler != nil {
130
+ handler(id)
131
+ }
132
+ }
133
+
134
+ //export electrobunWindowBlurHandler
135
+ func electrobunWindowBlurHandler(windowID C.uint32_t) {
136
+ id := uint32(windowID)
137
+ callbackMu.RLock()
138
+ handler := windowCallbackRegistry[id].Blur
139
+ callbackMu.RUnlock()
140
+ if handler != nil {
141
+ handler(id)
142
+ }
143
+ }
144
+
145
+ //export electrobunWindowKeyHandler
146
+ func electrobunWindowKeyHandler(windowID C.uint32_t, key C.uint32_t, modifiers C.uint32_t, eventType C.uint32_t, characters C.uint32_t) {
147
+ id := uint32(windowID)
148
+ callbackMu.RLock()
149
+ handler := windowCallbackRegistry[id].Key
150
+ callbackMu.RUnlock()
151
+ if handler != nil {
152
+ handler(id, uint32(key), uint32(modifiers), uint32(eventType), uint32(characters))
153
+ }
154
+ }
155
+
156
+ //export electrobunDecideNavigationHandler
157
+ func electrobunDecideNavigationHandler(webviewID C.uint32_t, url *C.char) C.uint32_t {
158
+ id := uint32(webviewID)
159
+ callbackMu.RLock()
160
+ handler := webviewCallbackRegistry[id].DecideNavigation
161
+ callbackMu.RUnlock()
162
+ if handler == nil {
163
+ return 1
164
+ }
165
+ return C.uint32_t(handler(id, C.GoString(url)))
166
+ }
167
+
168
+ //export electrobunWebviewEventHandler
169
+ func electrobunWebviewEventHandler(webviewID C.uint32_t, eventName *C.char, detail *C.char) {
170
+ id := uint32(webviewID)
171
+ callbackMu.RLock()
172
+ handler := webviewCallbackRegistry[id].Event
173
+ callbackMu.RUnlock()
174
+ if handler != nil {
175
+ handler(id, C.GoString(eventName), C.GoString(detail))
176
+ }
177
+ }
178
+
179
+ //export electrobunWebviewEventBridgeHandler
180
+ func electrobunWebviewEventBridgeHandler(webviewID C.uint32_t, message *C.char) {
181
+ id := uint32(webviewID)
182
+ callbackMu.RLock()
183
+ handler := webviewCallbackRegistry[id].EventBridge
184
+ callbackMu.RUnlock()
185
+ if handler != nil {
186
+ handler(id, C.GoString(message))
187
+ }
188
+ }
189
+
190
+ //export electrobunWebviewHostBridgeHandler
191
+ func electrobunWebviewHostBridgeHandler(webviewID C.uint32_t, message *C.char) {
192
+ id := uint32(webviewID)
193
+ callbackMu.RLock()
194
+ handler := webviewCallbackRegistry[id].HostBridge
195
+ callbackMu.RUnlock()
196
+ if handler != nil {
197
+ handler(id, C.GoString(message))
198
+ }
199
+ }
200
+
201
+ //export electrobunWebviewInternalBridgeHandler
202
+ func electrobunWebviewInternalBridgeHandler(webviewID C.uint32_t, message *C.char) {
203
+ id := uint32(webviewID)
204
+ callbackMu.RLock()
205
+ handler := webviewCallbackRegistry[id].InternalBridge
206
+ callbackMu.RUnlock()
207
+ if handler != nil {
208
+ handler(id, C.GoString(message))
209
+ }
210
+ }
211
+
212
+ //export electrobunStatusItemHandler
213
+ func electrobunStatusItemHandler(itemID C.uint32_t, message *C.char) {
214
+ callbackMu.RLock()
215
+ handler := statusItemHandler
216
+ callbackMu.RUnlock()
217
+ if handler != nil {
218
+ handler(uint32(itemID), C.GoString(message))
219
+ }
220
+ }
221
+
222
+ //export electrobunGlobalShortcutHandler
223
+ func electrobunGlobalShortcutHandler(accelerator *C.char) {
224
+ callbackMu.RLock()
225
+ handler := globalShortcutHandler
226
+ callbackMu.RUnlock()
227
+ if handler != nil {
228
+ handler(C.GoString(accelerator))
229
+ }
230
+ }
231
+
232
+ //export electrobunURLOpenHandler
233
+ func electrobunURLOpenHandler(url *C.char) {
234
+ callbackMu.RLock()
235
+ handler := urlOpenHandler
236
+ callbackMu.RUnlock()
237
+ if handler != nil {
238
+ handler(C.GoString(url))
239
+ }
240
+ }
241
+
242
+ //export electrobunAppReopenHandler
243
+ func electrobunAppReopenHandler() {
244
+ callbackMu.RLock()
245
+ handler := appReopenHandler
246
+ callbackMu.RUnlock()
247
+ if handler != nil {
248
+ handler()
249
+ }
250
+ }
251
+
252
+ //export electrobunQuitRequestedHandler
253
+ func electrobunQuitRequestedHandler() {
254
+ callbackMu.RLock()
255
+ handler := quitRequestedHandler
256
+ callbackMu.RUnlock()
257
+ if handler != nil {
258
+ handler()
259
+ }
260
+ }