electrobun 0.11.0-beta.3 → 0.13.0-beta.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.
@@ -14,12 +14,14 @@ import * as Socket from "./core/Socket";
14
14
  import type { ElectrobunConfig } from "./ElectrobunConfig";
15
15
  import { GlobalShortcut, Screen, Session } from "./proc/native";
16
16
  import type { Display, Rectangle, Point, Cookie, CookieFilter, StorageType } from "./proc/native";
17
+ import { BuildConfig, type BuildConfigType } from "./core/BuildConfig";
17
18
 
18
19
  // Named Exports
19
20
  export {
20
21
  type RPCSchema,
21
22
  type ElectrobunEvent,
22
23
  type ElectrobunConfig,
24
+ type BuildConfigType,
23
25
  type MessageBoxOptions,
24
26
  type MessageBoxResponse,
25
27
  type Display,
@@ -41,6 +43,7 @@ export {
41
43
  GlobalShortcut,
42
44
  Screen,
43
45
  Session,
46
+ BuildConfig,
44
47
  };
45
48
 
46
49
  // Default Export
@@ -55,6 +58,7 @@ const Electrobun = {
55
58
  GlobalShortcut,
56
59
  Screen,
57
60
  Session,
61
+ BuildConfig,
58
62
  events: electobunEventEmmitter,
59
63
  PATHS,
60
64
  Socket,
@@ -1,4 +1,4 @@
1
- import { join, resolve } from "path";
1
+ import { join } from "path";
2
2
  import { type RPCSchema, type RPCTransport, createRPC } from "rpc-anywhere";
3
3
  import { execSync } from "child_process";
4
4
  import * as fs from "fs";
@@ -62,7 +62,10 @@ import { BrowserWindow, BrowserWindowMap } from "../core/BrowserWindow";
62
62
 
63
63
  export const native = (() => {
64
64
  try {
65
- return dlopen(`./libNativeWrapper.${suffix}`, {
65
+ // Use absolute path to native wrapper DLL to avoid working directory issues
66
+ // On Windows shortcuts, the working directory may not be set correctly
67
+ const nativeWrapperPath = join(process.cwd(), `libNativeWrapper.${suffix}`);
68
+ return dlopen(nativeWrapperPath, {
66
69
  // window
67
70
  createWindowWithFrameAndStyleFromWorker: {
68
71
  // Pass each parameter individually
@@ -72,6 +75,7 @@ export const native = (() => {
72
75
  FFIType.f64, FFIType.f64, // width, height
73
76
  FFIType.u32, // styleMask
74
77
  FFIType.cstring, // titleBarStyle
78
+ FFIType.bool, // transparent
75
79
  FFIType.function, // closeHandler
76
80
  FFIType.function, // moveHandler
77
81
  FFIType.function, // resizeHandler
@@ -79,82 +83,99 @@ export const native = (() => {
79
83
  ],
80
84
  returns: FFIType.ptr
81
85
  },
82
- setNSWindowTitle: {
86
+ setWindowTitle: {
83
87
  args: [
84
88
  FFIType.ptr, // window ptr
85
89
  FFIType.cstring, // title
86
90
  ],
87
91
  returns: FFIType.void,
88
92
  },
89
- makeNSWindowKeyAndOrderFront: {
93
+ showWindow: {
90
94
  args: [
91
- FFIType.ptr, // window ptr
95
+ FFIType.ptr, // window ptr
92
96
  ],
93
97
  returns: FFIType.void,
94
98
  },
95
- closeNSWindow: {
99
+ closeWindow: {
96
100
  args: [
97
101
  FFIType.ptr, // window ptr
98
102
  ],
99
103
  returns: FFIType.void,
100
104
  },
101
- minimizeNSWindow: {
105
+ minimizeWindow: {
102
106
  args: [FFIType.ptr],
103
107
  returns: FFIType.void,
104
108
  },
105
- unminimizeNSWindow: {
109
+ restoreWindow: {
106
110
  args: [FFIType.ptr],
107
111
  returns: FFIType.void,
108
112
  },
109
- isNSWindowMinimized: {
113
+ isWindowMinimized: {
110
114
  args: [FFIType.ptr],
111
115
  returns: FFIType.bool,
112
116
  },
113
- maximizeNSWindow: {
117
+ maximizeWindow: {
114
118
  args: [FFIType.ptr],
115
119
  returns: FFIType.void,
116
120
  },
117
- unmaximizeNSWindow: {
121
+ unmaximizeWindow: {
118
122
  args: [FFIType.ptr],
119
123
  returns: FFIType.void,
120
124
  },
121
- isNSWindowMaximized: {
125
+ isWindowMaximized: {
122
126
  args: [FFIType.ptr],
123
127
  returns: FFIType.bool,
124
128
  },
125
- setNSWindowFullScreen: {
129
+ setWindowFullScreen: {
126
130
  args: [FFIType.ptr, FFIType.bool],
127
131
  returns: FFIType.void,
128
132
  },
129
- isNSWindowFullScreen: {
133
+ isWindowFullScreen: {
130
134
  args: [FFIType.ptr],
131
135
  returns: FFIType.bool,
132
136
  },
133
- setNSWindowAlwaysOnTop: {
137
+ setWindowAlwaysOnTop: {
134
138
  args: [FFIType.ptr, FFIType.bool],
135
139
  returns: FFIType.void,
136
140
  },
137
- isNSWindowAlwaysOnTop: {
141
+ isWindowAlwaysOnTop: {
138
142
  args: [FFIType.ptr],
139
143
  returns: FFIType.bool,
140
144
  },
145
+ setWindowPosition: {
146
+ args: [FFIType.ptr, FFIType.f64, FFIType.f64],
147
+ returns: FFIType.void,
148
+ },
149
+ setWindowSize: {
150
+ args: [FFIType.ptr, FFIType.f64, FFIType.f64],
151
+ returns: FFIType.void,
152
+ },
153
+ setWindowFrame: {
154
+ args: [FFIType.ptr, FFIType.f64, FFIType.f64, FFIType.f64, FFIType.f64],
155
+ returns: FFIType.void,
156
+ },
157
+ getWindowFrame: {
158
+ args: [FFIType.ptr, FFIType.ptr, FFIType.ptr, FFIType.ptr, FFIType.ptr],
159
+ returns: FFIType.void,
160
+ },
141
161
  // webview
142
162
  initWebview: {
143
163
  args: [
144
164
  FFIType.u32, // webviewId
145
165
  FFIType.ptr, // windowPtr
146
- FFIType.cstring, // renderer
147
- FFIType.cstring, // url
166
+ FFIType.cstring, // renderer
167
+ FFIType.cstring, // url
148
168
  FFIType.f64, FFIType.f64, // x, y
149
- FFIType.f64, FFIType.f64, // width, height
169
+ FFIType.f64, FFIType.f64, // width, height
150
170
  FFIType.bool, // autoResize
151
- FFIType.cstring, // partition
171
+ FFIType.cstring, // partition
152
172
  FFIType.function, // decideNavigation: *const fn (u32, [*:0]const u8) callconv(.C) bool,
153
173
  FFIType.function, // webviewEventHandler: *const fn (u32, [*:0]const u8, [*:0]const u8) callconv(.C) void,
154
174
  FFIType.function, // bunBridgePostmessageHandler: *const fn (u32, [*:0]const u8) callconv(.C) void,
155
175
  FFIType.function, // internalBridgeHandler: *const fn (u32, [*:0]const u8) callconv(.C) void,
156
176
  FFIType.cstring, // electrobunPreloadScript
157
177
  FFIType.cstring, // customPreloadScript
178
+ FFIType.bool, // transparent
158
179
  ],
159
180
  returns: FFIType.ptr
160
181
  },
@@ -440,8 +461,8 @@ export const native = (() => {
440
461
  returns: FFIType.void
441
462
  },
442
463
 
443
- // MacOS specific native utils
444
- getNSWindowStyleMask: {
464
+ // Window style utilities
465
+ getWindowStyle: {
445
466
  args: [
446
467
  FFIType.bool,
447
468
  FFIType.bool,
@@ -466,6 +487,13 @@ export const native = (() => {
466
487
  ],
467
488
  returns: FFIType.void
468
489
  },
490
+ setWindowIcon: {
491
+ args: [
492
+ FFIType.ptr, // window pointer
493
+ FFIType.cstring, // icon path
494
+ ],
495
+ returns: FFIType.void
496
+ },
469
497
  killApp: {
470
498
  args: [],
471
499
  returns: FFIType.void
@@ -504,7 +532,7 @@ export const ffi = {
504
532
  request: {
505
533
  createWindow: (params: {
506
534
  id: number,
507
- url: string | null,
535
+ url: string | null,
508
536
  title: string,
509
537
  frame: {
510
538
  width: number,
@@ -527,6 +555,7 @@ export const ffi = {
527
555
  HUDWindow: boolean,
528
556
  },
529
557
  titleBarStyle: string,
558
+ transparent: boolean,
530
559
  }): FFIType.ptr => {
531
560
  const {id, url, title, frame: {x, y, width, height}, styleMask: {
532
561
  Borderless,
@@ -541,10 +570,11 @@ export const ffi = {
541
570
  DocModalWindow,
542
571
  NonactivatingPanel,
543
572
  HUDWindow
544
- },
545
- titleBarStyle} = params
546
-
547
- const styleMask = native.symbols.getNSWindowStyleMask(
573
+ },
574
+ titleBarStyle,
575
+ transparent} = params
576
+
577
+ const styleMask = native.symbols.getWindowStyle(
548
578
  Borderless,
549
579
  Titled,
550
580
  Closable,
@@ -557,8 +587,8 @@ export const ffi = {
557
587
  DocModalWindow,
558
588
  NonactivatingPanel,
559
589
  HUDWindow
560
- )
561
-
590
+ )
591
+
562
592
  const windowPtr = native.symbols.createWindowWithFrameAndStyleFromWorker(
563
593
  id,
564
594
  // frame
@@ -566,6 +596,7 @@ export const ffi = {
566
596
  styleMask,
567
597
  // style
568
598
  toCString(titleBarStyle),
599
+ transparent,
569
600
  // callbacks
570
601
  windowCloseCallback,
571
602
  windowMoveCallback,
@@ -578,11 +609,8 @@ export const ffi = {
578
609
  throw "Failed to create window"
579
610
  }
580
611
 
581
- native.symbols.setNSWindowTitle(windowPtr, toCString(title));
582
- // setTimeout(() => {
583
- // console.log('calling makeNSWindowKeyAndOrderFront', windowPtr)
584
- native.symbols.makeNSWindowKeyAndOrderFront(windowPtr);
585
- // }, 1000)
612
+ native.symbols.setWindowTitle(windowPtr, toCString(title));
613
+ native.symbols.showWindow(windowPtr);
586
614
 
587
615
  return windowPtr;
588
616
  },
@@ -595,7 +623,7 @@ export const ffi = {
595
623
  throw `Can't add webview to window. window no longer exists`;
596
624
  }
597
625
 
598
- native.symbols.setNSWindowTitle(windowPtr, toCString(title));
626
+ native.symbols.setWindowTitle(windowPtr, toCString(title));
599
627
  },
600
628
 
601
629
  closeWindow: (params: {winId: number}) => {
@@ -606,7 +634,7 @@ export const ffi = {
606
634
  throw `Can't close window. Window no longer exists`;
607
635
  }
608
636
 
609
- native.symbols.closeNSWindow(windowPtr);
637
+ native.symbols.closeWindow(windowPtr);
610
638
  // Note: Cleanup of BrowserWindowMap happens in the windowCloseCallback
611
639
  },
612
640
 
@@ -618,7 +646,7 @@ export const ffi = {
618
646
  throw `Can't focus window. Window no longer exists`;
619
647
  }
620
648
 
621
- native.symbols.makeNSWindowKeyAndOrderFront(windowPtr);
649
+ native.symbols.showWindow(windowPtr);
622
650
  },
623
651
 
624
652
  minimizeWindow: (params: {winId: number}) => {
@@ -629,18 +657,18 @@ export const ffi = {
629
657
  throw `Can't minimize window. Window no longer exists`;
630
658
  }
631
659
 
632
- native.symbols.minimizeNSWindow(windowPtr);
660
+ native.symbols.minimizeWindow(windowPtr);
633
661
  },
634
662
 
635
- unminimizeWindow: (params: {winId: number}) => {
663
+ restoreWindow: (params: {winId: number}) => {
636
664
  const {winId} = params;
637
665
  const windowPtr = BrowserWindow.getById(winId)?.ptr;
638
666
 
639
667
  if (!windowPtr) {
640
- throw `Can't unminimize window. Window no longer exists`;
668
+ throw `Can't restore window. Window no longer exists`;
641
669
  }
642
670
 
643
- native.symbols.unminimizeNSWindow(windowPtr);
671
+ native.symbols.restoreWindow(windowPtr);
644
672
  },
645
673
 
646
674
  isWindowMinimized: (params: {winId: number}): boolean => {
@@ -651,7 +679,7 @@ export const ffi = {
651
679
  return false;
652
680
  }
653
681
 
654
- return native.symbols.isNSWindowMinimized(windowPtr);
682
+ return native.symbols.isWindowMinimized(windowPtr);
655
683
  },
656
684
 
657
685
  maximizeWindow: (params: {winId: number}) => {
@@ -662,7 +690,7 @@ export const ffi = {
662
690
  throw `Can't maximize window. Window no longer exists`;
663
691
  }
664
692
 
665
- native.symbols.maximizeNSWindow(windowPtr);
693
+ native.symbols.maximizeWindow(windowPtr);
666
694
  },
667
695
 
668
696
  unmaximizeWindow: (params: {winId: number}) => {
@@ -673,7 +701,7 @@ export const ffi = {
673
701
  throw `Can't unmaximize window. Window no longer exists`;
674
702
  }
675
703
 
676
- native.symbols.unmaximizeNSWindow(windowPtr);
704
+ native.symbols.unmaximizeWindow(windowPtr);
677
705
  },
678
706
 
679
707
  isWindowMaximized: (params: {winId: number}): boolean => {
@@ -684,7 +712,7 @@ export const ffi = {
684
712
  return false;
685
713
  }
686
714
 
687
- return native.symbols.isNSWindowMaximized(windowPtr);
715
+ return native.symbols.isWindowMaximized(windowPtr);
688
716
  },
689
717
 
690
718
  setWindowFullScreen: (params: {winId: number; fullScreen: boolean}) => {
@@ -695,7 +723,7 @@ export const ffi = {
695
723
  throw `Can't set fullscreen. Window no longer exists`;
696
724
  }
697
725
 
698
- native.symbols.setNSWindowFullScreen(windowPtr, fullScreen);
726
+ native.symbols.setWindowFullScreen(windowPtr, fullScreen);
699
727
  },
700
728
 
701
729
  isWindowFullScreen: (params: {winId: number}): boolean => {
@@ -706,7 +734,7 @@ export const ffi = {
706
734
  return false;
707
735
  }
708
736
 
709
- return native.symbols.isNSWindowFullScreen(windowPtr);
737
+ return native.symbols.isWindowFullScreen(windowPtr);
710
738
  },
711
739
 
712
740
  setWindowAlwaysOnTop: (params: {winId: number; alwaysOnTop: boolean}) => {
@@ -717,7 +745,7 @@ export const ffi = {
717
745
  throw `Can't set always on top. Window no longer exists`;
718
746
  }
719
747
 
720
- native.symbols.setNSWindowAlwaysOnTop(windowPtr, alwaysOnTop);
748
+ native.symbols.setWindowAlwaysOnTop(windowPtr, alwaysOnTop);
721
749
  },
722
750
 
723
751
  isWindowAlwaysOnTop: (params: {winId: number}): boolean => {
@@ -728,7 +756,70 @@ export const ffi = {
728
756
  return false;
729
757
  }
730
758
 
731
- return native.symbols.isNSWindowAlwaysOnTop(windowPtr);
759
+ return native.symbols.isWindowAlwaysOnTop(windowPtr);
760
+ },
761
+
762
+ setWindowPosition: (params: {winId: number; x: number; y: number}) => {
763
+ const {winId, x, y} = params;
764
+ const windowPtr = BrowserWindow.getById(winId)?.ptr;
765
+
766
+ if (!windowPtr) {
767
+ throw `Can't set window position. Window no longer exists`;
768
+ }
769
+
770
+ native.symbols.setWindowPosition(windowPtr, x, y);
771
+ },
772
+
773
+ setWindowSize: (params: {winId: number; width: number; height: number}) => {
774
+ const {winId, width, height} = params;
775
+ const windowPtr = BrowserWindow.getById(winId)?.ptr;
776
+
777
+ if (!windowPtr) {
778
+ throw `Can't set window size. Window no longer exists`;
779
+ }
780
+
781
+ native.symbols.setWindowSize(windowPtr, width, height);
782
+ },
783
+
784
+ setWindowFrame: (params: {winId: number; x: number; y: number; width: number; height: number}) => {
785
+ const {winId, x, y, width, height} = params;
786
+ const windowPtr = BrowserWindow.getById(winId)?.ptr;
787
+
788
+ if (!windowPtr) {
789
+ throw `Can't set window frame. Window no longer exists`;
790
+ }
791
+
792
+ native.symbols.setWindowFrame(windowPtr, x, y, width, height);
793
+ },
794
+
795
+ getWindowFrame: (params: {winId: number}): {x: number; y: number; width: number; height: number} => {
796
+ const {winId} = params;
797
+ const windowPtr = BrowserWindow.getById(winId)?.ptr;
798
+
799
+ if (!windowPtr) {
800
+ return {x: 0, y: 0, width: 0, height: 0};
801
+ }
802
+
803
+ // Create buffers to receive the output values
804
+ const xBuf = new Float64Array(1);
805
+ const yBuf = new Float64Array(1);
806
+ const widthBuf = new Float64Array(1);
807
+ const heightBuf = new Float64Array(1);
808
+
809
+ native.symbols.getWindowFrame(
810
+ windowPtr,
811
+ ptr(xBuf),
812
+ ptr(yBuf),
813
+ ptr(widthBuf),
814
+ ptr(heightBuf)
815
+ );
816
+
817
+ return {
818
+ x: xBuf[0],
819
+ y: yBuf[0],
820
+ width: widthBuf[0],
821
+ height: heightBuf[0],
822
+ };
732
823
  },
733
824
 
734
825
  createWebview: (params: {
@@ -739,8 +830,8 @@ export const ffi = {
739
830
  secretKey: string;
740
831
  hostWebviewId: number | null;
741
832
  pipePrefix: string;
742
- url: string | null;
743
- html: string | null;
833
+ url: string | null;
834
+ html: string | null;
744
835
  partition: string | null;
745
836
  preload: string | null;
746
837
  frame: {
@@ -761,7 +852,7 @@ export const ffi = {
761
852
  // hostWebviewId: number | null;
762
853
  // pipePrefix: string;
763
854
  url,
764
- // html: string | null;
855
+ // html: string | null;
765
856
  partition,
766
857
  preload,
767
858
  frame: {
@@ -772,7 +863,10 @@ export const ffi = {
772
863
  },
773
864
  autoResize} = params
774
865
 
775
- const windowPtr = BrowserWindow.getById(windowId)?.ptr;
866
+ const parentWindow = BrowserWindow.getById(windowId);
867
+ const windowPtr = parentWindow?.ptr;
868
+ // Get transparent flag from parent window
869
+ const transparent = parentWindow?.transparent ?? false;
776
870
 
777
871
 
778
872
  if (!windowPtr) {
@@ -983,9 +1077,9 @@ export const ffi = {
983
1077
  id,
984
1078
  windowPtr,
985
1079
  toCString(renderer),
986
- toCString(url || ''),
987
- x, y,
988
- width, height,
1080
+ toCString(url || ''),
1081
+ x, y,
1082
+ width, height,
989
1083
  autoResize,
990
1084
  toCString(partition || 'persist:default'),
991
1085
  webviewDecideNavigation,
@@ -993,7 +1087,8 @@ export const ffi = {
993
1087
  bunBridgePostmessageHandler,
994
1088
  internalBridgeHandler,
995
1089
  toCString(electrobunPreload),
996
- toCString(customPreload || ''),
1090
+ toCString(customPreload || ''),
1091
+ transparent,
997
1092
  )
998
1093
 
999
1094
  if (!webviewPtr) {
@@ -1785,6 +1880,9 @@ const webviewEventHandler = (id, eventName, detail) => {
1785
1880
  "download-progress": "downloadProgress",
1786
1881
  "download-completed": "downloadCompleted",
1787
1882
  "download-failed": "downloadFailed",
1883
+ "load-started": "loadStarted",
1884
+ "load-committed": "loadCommitted",
1885
+ "load-finished": "loadFinished",
1788
1886
  };
1789
1887
 
1790
1888
  // todo: the events map should use the same hyphenated names instead of camelCase
package/dist/main.js CHANGED
@@ -12,6 +12,7 @@ var absoluteLibPath = resolve(libPath);
12
12
  function main() {
13
13
  let channel = "";
14
14
  let identifier = "";
15
+ let name = "";
15
16
  try {
16
17
  const pathToLauncherBin2 = process.argv0;
17
18
  const pathToBinDir2 = dirname(pathToLauncherBin2);
@@ -21,10 +22,13 @@ function main() {
21
22
  if (versionInfo.identifier) {
22
23
  identifier = versionInfo.identifier;
23
24
  }
25
+ if (versionInfo.name) {
26
+ name = versionInfo.name;
27
+ }
24
28
  if (versionInfo.channel) {
25
29
  channel = versionInfo.channel;
26
30
  }
27
- console.log(`[LAUNCHER] Loaded identifier: ${identifier}, channel: ${channel}`);
31
+ console.log(`[LAUNCHER] Loaded identifier: ${identifier}, name: ${name}, channel: ${channel}`);
28
32
  }
29
33
  } catch (error) {
30
34
  console.error(`[LAUNCHER] Warning: Could not read version.json:`, error);
@@ -52,13 +56,13 @@ function main() {
52
56
  process.env.LD_LIBRARY_PATH = `.${process.env.LD_LIBRARY_PATH ? ":" + process.env.LD_LIBRARY_PATH : ""}`;
53
57
  }
54
58
  lib = dlopen(libPath, {
55
- runNSApplication: { args: ["cstring", "cstring"], returns: "void" }
59
+ startEventLoop: { args: ["cstring", "cstring", "cstring"], returns: "void" }
56
60
  });
57
61
  } catch (error) {
58
62
  console.error(`[LAUNCHER] Failed to load library: ${error.message}`);
59
63
  try {
60
64
  lib = dlopen(absoluteLibPath, {
61
- runNSApplication: { args: ["cstring", "cstring"], returns: "void" }
65
+ startEventLoop: { args: ["cstring", "cstring", "cstring"], returns: "void" }
62
66
  });
63
67
  } catch (absError) {
64
68
  console.error(`[LAUNCHER] Library loading failed. Try running: ldd ${libPath}`);
@@ -135,6 +139,6 @@ ${fileData.toString("utf8")}
135
139
  appEntrypointPath = join(appFolderPath, "bun", "index.js");
136
140
  }
137
141
  new Worker(appEntrypointPath, {});
138
- lib.symbols.runNSApplication(ptr(Buffer.from(identifier + "\x00", "utf8")), ptr(Buffer.from(channel + "\x00", "utf8")));
142
+ lib.symbols.startEventLoop(ptr(Buffer.from(identifier + "\x00", "utf8")), ptr(Buffer.from(name + "\x00", "utf8")), ptr(Buffer.from(channel + "\x00", "utf8")));
139
143
  }
140
144
  main();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "electrobun",
3
- "version": "0.11.0-beta.3",
3
+ "version": "0.13.0-beta.1",
4
4
  "description": "Build ultra fast, tiny, and cross-platform desktop apps with Typescript.",
5
5
  "license": "MIT",
6
6
  "author": "Blackboard Technologies Inc.",
@@ -55,6 +55,8 @@
55
55
  "dependencies": {
56
56
  "@oneidentity/zstd-js": "^1.0.3",
57
57
  "archiver": "^7.0.1",
58
+ "png-to-ico": "^2.1.8",
59
+ "rcedit": "^4.0.1",
58
60
  "rpc-anywhere": "1.5.0",
59
61
  "tar": "^6.2.1"
60
62
  }