@yufengtadian/freedom-cli 1.12.1 → 1.12.12

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 (55) hide show
  1. package/README.md +24 -14
  2. package/lib/cli.js +6 -6
  3. package/lib/config.js +115 -31
  4. package/lib/tui.js +1 -1
  5. package/package.json +1 -1
  6. package/shell/win-x64/freedom-shell.exe +0 -0
  7. package/templates/go/build_out.txt +0 -0
  8. package/templates/go/err.txt +2 -0
  9. package/templates/go/err10.txt +0 -0
  10. package/templates/go/err11.txt +0 -0
  11. package/templates/go/err2.txt +0 -0
  12. package/templates/go/err3.txt +0 -0
  13. package/templates/go/err4.txt +1 -0
  14. package/templates/go/err5.txt +0 -0
  15. package/templates/go/err6.txt +0 -0
  16. package/templates/go/err7.txt +0 -0
  17. package/templates/go/err8.txt +0 -0
  18. package/templates/go/err9.txt +0 -0
  19. package/templates/go/go.mod +6 -0
  20. package/templates/go/go.mod.bak_gbk +11 -0
  21. package/templates/go/go.sum +2 -2
  22. package/templates/go/pkg/freedom/assets/freedom.js +6 -0
  23. package/templates/go/pkg/freedom/assets/index.html +1 -1
  24. package/templates/go/pkg/freedom/configfile.go +0 -2
  25. package/templates/go/pkg/freedom/freedom.go +16 -10
  26. package/templates/go/pkg/freedom/window_other.go +60 -12
  27. package/templates/go/pkg/freedom/window_windows.go +244 -29
  28. package/templates/go/tidy.txt +0 -0
  29. package/templates/go/vet_out.txt +0 -0
  30. package/templates/go/webview_go/.github/workflows/ci.yaml +62 -0
  31. package/templates/go/webview_go/CHANGELOG.md +15 -0
  32. package/templates/go/webview_go/LICENSE +22 -0
  33. package/templates/go/webview_go/README.md +50 -0
  34. package/templates/go/webview_go/examples/basic/main.go +12 -0
  35. package/templates/go/webview_go/examples/bind/main.go +38 -0
  36. package/templates/go/webview_go/glue.c +36 -0
  37. package/templates/go/webview_go/go.mod +3 -0
  38. package/templates/go/webview_go/go.sum +0 -0
  39. package/templates/go/webview_go/libs/mswebview2/LICENSE +27 -0
  40. package/templates/go/webview_go/libs/mswebview2/include/WebView2.h +23568 -0
  41. package/templates/go/webview_go/libs/mswebview2/include/vendor.go +2 -0
  42. package/templates/go/webview_go/libs/mswebview2/vendor.go +2 -0
  43. package/templates/go/webview_go/libs/mswebview2/version.txt +1 -0
  44. package/templates/go/webview_go/libs/webview/LICENSE +22 -0
  45. package/templates/go/webview_go/libs/webview/include/vendor.go +2 -0
  46. package/templates/go/webview_go/libs/webview/include/webview.h +3840 -0
  47. package/templates/go/webview_go/libs/webview/vendor.go +2 -0
  48. package/templates/go/webview_go/libs/webview/version.txt +1 -0
  49. package/templates/go/webview_go/webview.cc +1 -0
  50. package/templates/go/webview_go/webview.go +371 -0
  51. package/templates/go/webview_go/webview_test.go +50 -0
  52. package/templates/project/freedom.config.js +5 -5
  53. package/templates/project/index.html +45 -5
  54. package/templates/project/src/main.js +140 -6
  55. package/tutorial/tutorial.html +4 -5
@@ -3,9 +3,16 @@
3
3
  package freedom
4
4
 
5
5
  import (
6
+ "bytes"
7
+ "encoding/base64"
8
+ "encoding/binary"
6
9
  "fmt"
10
+ "image"
11
+ "image/color"
12
+ "image/png"
7
13
  "syscall"
8
- "unsafe"
14
+
15
+ "golang.org/x/sys/windows"
9
16
  )
10
17
 
11
18
  // 进程级 DPI 感知:让窗口坐标 / WebView 渲染统一按物理像素工作。
@@ -27,6 +34,7 @@ func init() {
27
34
 
28
35
  var (
29
36
  user32win = syscall.NewLazyDLL("user32.dll")
37
+ kernel32 = syscall.NewLazyDLL("kernel32.dll")
30
38
 
31
39
  procGetWindowLongPtr = user32win.NewProc("GetWindowLongPtrW")
32
40
  procSetWindowLongPtr = user32win.NewProc("SetWindowLongPtrW")
@@ -35,22 +43,41 @@ var (
35
43
  procSetWindowPos = user32win.NewProc("SetWindowPos")
36
44
  procSetWindowText = user32win.NewProc("SetWindowTextW")
37
45
  procPostMessage = user32win.NewProc("PostMessageW")
46
+ procGetModuleHandle = kernel32.NewProc("GetModuleHandleW")
47
+ procLoadImage = user32win.NewProc("LoadImageW")
48
+ procGetSystemMetrics = user32win.NewProc("GetSystemMetrics")
49
+ procSendMessage = user32win.NewProc("SendMessageW")
50
+ procReleaseCapture = user32win.NewProc("ReleaseCapture")
51
+ procGetWindowRect = user32win.NewProc("GetWindowRect")
52
+ procMonitorFromWindow = user32win.NewProc("MonitorFromWindow")
53
+ procGetMonitorInfo = user32win.NewProc("GetMonitorInfoW")
54
+ procMoveWindow = user32win.NewProc("MoveWindow")
55
+
56
+ procDestroyIcon = user32win.NewProc("DestroyIcon")
38
57
 
39
58
  dwmapi = syscall.NewLazyDLL("dwmapi.dll")
40
59
  procDwmExtendFrameIntoArea = dwmapi.NewProc("DwmExtendFrameIntoClientArea")
41
60
  )
42
61
 
43
62
  const (
44
- wsCaption = 0x00C00000 // WS_CAPTION = WS_BORDER | WS_DLGFRAME
45
- wsSysMenu = 0x00080000
63
+ wsCaption = 0x00C00000 // WS_CAPTION = WS_BORDER | WS_DLGFRAME
64
+ wsSysMenu = 0x00080000
46
65
  wsThickFrame = 0x00040000
47
66
 
48
- wmClose = 0x0010 // WM_CLOSE:请求窗口正常关闭(触发 GoWnd 的关闭回调)
49
- swHide = 0
50
- swShow = 5
51
- swMinimize = 6
52
- swRestore = 9
53
- swMaximize = 3
67
+ wmClose = 0x0010 // WM_CLOSE:请求窗口正常关闭(触发 GoWnd 的关闭回调)
68
+ wmSetIcon = 0x0080 // WM_SETICON:设置窗口大/小图标(ICON_BIG=1 / ICON_SMALL=0)
69
+
70
+ rtIcon = 3 // RT_ICON 资源类型(rcedit 注入图标二进制)
71
+ swHide = 0
72
+ swShow = 5
73
+ swMinimize = 6
74
+ swRestore = 9
75
+ swMaximize = 3
76
+
77
+ smCXIcon = 11 // SM_CXICON
78
+ smCYIcon = 12 // SM_CYICON
79
+ smCXSmall = 13 // SM_CXSMICON
80
+ smCYSmall = 14 // SM_CYSMICON
54
81
 
55
82
  swpFrameChanged = 0x0020
56
83
  swpNoMove = 0x0002
@@ -82,7 +109,8 @@ func refreshFrame(hwnd uintptr) {
82
109
  }
83
110
 
84
111
  // windowControl 处理前端 window.freedom.window.* 请求(Windows 实现)。
85
- func windowControl(hwnd uintptr, action string, mode TitleBarMode) (interface{}, error) {
112
+ func windowControl(a *App, action string) (interface{}, error) {
113
+ hwnd := a.WindowHandle()
86
114
  if hwnd == 0 {
87
115
  return nil, fmt.Errorf("window not ready")
88
116
  }
@@ -91,16 +119,16 @@ func windowControl(hwnd uintptr, action string, mode TitleBarMode) (interface{},
91
119
  procShowWindow.Call(hwnd, swMinimize)
92
120
  return nil, nil
93
121
  case "maximize":
94
- procShowWindow.Call(hwnd, swMaximize)
122
+ maximizeWindow(hwnd)
95
123
  return nil, nil
96
124
  case "unmaximize", "restore":
97
- procShowWindow.Call(hwnd, swRestore)
125
+ restoreWindow(hwnd)
98
126
  return nil, nil
99
127
  case "toggleMaximize":
100
- if isZoomed(hwnd) {
101
- procShowWindow.Call(hwnd, swRestore)
128
+ if isWindowMaximized(hwnd) {
129
+ restoreWindow(hwnd)
102
130
  } else {
103
- procShowWindow.Call(hwnd, swMaximize)
131
+ maximizeWindow(hwnd)
104
132
  }
105
133
  return nil, nil
106
134
  case "close":
@@ -109,14 +137,101 @@ func windowControl(hwnd uintptr, action string, mode TitleBarMode) (interface{},
109
137
  procPostMessage.Call(hwnd, wmClose, 0, 0)
110
138
  return nil, nil
111
139
  case "isMaximized":
112
- return isZoomed(hwnd), nil
140
+ return isWindowMaximized(hwnd), nil
113
141
  case "isFrameless":
114
- return mode == TitleBarFrameless || mode == TitleBarHidden, nil
142
+ return a.cfg.TitleBar == TitleBarFrameless, nil
143
+ case "appIcon":
144
+ // 从 exe 内嵌图标(PE 资源 ID=1)提取,转为 PNG data URL 供前端标题栏显示。
145
+ // 不依赖 resources 文件夹里的任何图标文件。
146
+ return exeAppIconDataURL(), nil
147
+ case "startDrag":
148
+ // 前端标题栏 mousedown 时发起窗口拖动(WM_NCLBUTTONDOWN + HTCAPTION)。
149
+ // 相比 -webkit-app-region: drag,可保留双击最大化 / 右键菜单等页面事件。
150
+ procReleaseCapture.Call()
151
+ procSendMessage.Call(hwnd, 0x00A1 /*WM_NCLBUTTONDOWN*/, 2 /*HTCAPTION*/, 0)
152
+ return nil, nil
115
153
  default:
116
154
  return nil, fmt.Errorf("unknown window action %q", action)
117
155
  }
118
156
  }
119
157
 
158
+ // maximizeWindow 最大化窗口。
159
+ // 直接走系统 SW_MAXIMIZE:壳层(webview_go fork)在 WndProc 的 WM_GETMINMAXINFO 中
160
+ // 已把无边框窗口的最大化边界限定到监视器工作区(rcWork),
161
+ // 因此"最大化 = 铺满任务栏上方的工作区",而非 F11 式整屏全屏。
162
+ func maximizeWindow(hwnd uintptr) {
163
+ procShowWindow.Call(hwnd, swMaximize)
164
+ }
165
+
166
+ // restoreWindow 还原窗口(系统 SW_RESTORE,恢复到最大化前的位置与尺寸)。
167
+ func restoreWindow(hwnd uintptr) {
168
+ procShowWindow.Call(hwnd, swRestore)
169
+ }
170
+
171
+ // isWindowMaximized 判断窗口当前是否处于最大化状态。
172
+ func isWindowMaximized(hwnd uintptr) bool {
173
+ return isZoomed(hwnd)
174
+ }
175
+
176
+ // exeIconData 读取当前 exe 内嵌的 RT_ICON 资源原始字节(rcedit 注入时资源 ID=1)。
177
+ // 不依赖 RT_GROUP_ICON 的 ID(rcedit 固定写入 0,而 LoadImageW 按硬编码 ID 加载会失败),
178
+ // 直接取 RT_ICON 二进制,兼容任意注入工具。
179
+ // 使用 x/sys/windows 类型化 API(LoadResourceData 直接返回字节副本,无需 unsafe 指针转换)。
180
+ func exeIconData() []byte {
181
+ var hInst windows.Handle
182
+ if err := windows.GetModuleHandleEx(0, nil, &hInst); err != nil {
183
+ return nil
184
+ }
185
+ // FindResourceW(hModule, MAKEINTRESOURCE(1), MAKEINTRESOURCE(RT_ICON))
186
+ resInfo, err := windows.FindResource(hInst, windows.ResourceID(1), windows.ResourceID(rtIcon))
187
+ if err != nil {
188
+ return nil
189
+ }
190
+ data, err := windows.LoadResourceData(hInst, resInfo)
191
+ if err != nil {
192
+ return nil
193
+ }
194
+ return data
195
+ }
196
+
197
+ // isPNG 判断字节流是否为 PNG 编码(rcedit 注入的 .ico 内嵌 PNG 时 RT_ICON 数据即 PNG)。
198
+ func isPNG(b []byte) bool {
199
+ return len(b) >= 8 && b[0] == 0x89 && b[1] == 'P' && b[2] == 'N' && b[3] == 'G'
200
+ }
201
+
202
+ // loadExeIcon 从 exe 内嵌的 RT_GROUP_ICON 资源加载 HICON。
203
+ // rcedit 注入的 group icon 资源 ID 固定为 0(LoadImageW 需按该 ID 加载;
204
+ // 历史按 ID=1 硬编码导致加载失败,故此处显式用 0)。
205
+ // 调用方用完须 procDestroyIcon 释放;加载失败返回 0。
206
+ func loadExeIcon(cx, cy uintptr) uintptr {
207
+ hInst, _, _ := procGetModuleHandle.Call(0)
208
+ if hInst == 0 {
209
+ return 0
210
+ }
211
+ // LoadImageW(hInst, MAKEINTRESOURCE(0), IMAGE_ICON, cx, cy, LR_DEFAULTCOLOR)
212
+ r, _, _ := procLoadImage.Call(hInst, 0, 1 /*IMAGE_ICON*/, cx, cy, 0 /*LR_DEFAULTCOLOR*/)
213
+ return r
214
+ }
215
+
216
+ // exeAppIconDataURL 从当前 exe 的 PE 资源图标(rcedit 注入的 RT_ICON)提取为 PNG data URL。
217
+ // 无法提取时返回空字符串(前端隐藏图标)。
218
+ func exeAppIconDataURL() string {
219
+ data := exeIconData()
220
+ if len(data) == 0 {
221
+ return ""
222
+ }
223
+ // rcedit 注入 .ico 内嵌 PNG 时,RT_ICON 数据即 PNG 字节,直接编码
224
+ if isPNG(data) {
225
+ return "data:image/png;base64," + base64.StdEncoding.EncodeToString(data)
226
+ }
227
+ // 非 PNG(BMP/DIB):纯 Go 解析像素并编码为 PNG,无需 GDI 绘制
228
+ img, err := dibToPNG(data)
229
+ if err != nil {
230
+ return ""
231
+ }
232
+ return "data:image/png;base64," + base64.StdEncoding.EncodeToString(img)
233
+ }
234
+
120
235
  func isZoomed(hwnd uintptr) bool {
121
236
  r, _, _ := procIsZoomed.Call(hwnd)
122
237
  return r != 0
@@ -130,21 +245,121 @@ func (a *App) applyTitleBar() {
130
245
  }
131
246
  switch a.cfg.TitleBar {
132
247
  case TitleBarFrameless:
133
- // 完全无边框:去掉标题栏 / 系统菜单,客户区铺满整个窗口。
134
- // 最小化 / 最大化 / 关闭按钮由前端自绘(window.freedom.window.*)。
248
+ // 完全无边框:去掉标题栏 / 系统菜单 / 可调边框(WS_THICKFRAME)。
249
+ // - 标题栏与系统原生最小化 / 最大化 / 关闭按钮均不存在,由前端自绘
250
+ // (window.freedom.window.*)接管;
251
+ // - 去掉 WS_THICKFRAME 是最大化行为正确的关键:只要该位存在,系统在
252
+ // WM_GETMINMAXINFO 之后仍会按 AdjustWindowRectEx 追加标题栏 + 边框空间,
253
+ // 导致最大化窗口溢出工作区、盖住任务栏(F11 全屏感);
254
+ // - 边缘拖拽 resize 由壳层 WndProc 的 WM_NCHITTEST 手动实现(返回 HT* 边界值),
255
+ // 不依赖 WS_THICKFRAME。
135
256
  style := getWindowStyle(hwnd)
136
- style &^= wsCaption | wsSysMenu
257
+ style &^= wsCaption | wsSysMenu | wsThickFrame
137
258
  setWindowStyle(hwnd, style)
138
259
  refreshFrame(hwnd)
139
- case TitleBarHidden:
140
- // 隐藏标题栏视觉但保留系统原生按钮:DWM 玻璃扩展。
141
- // 标题栏区域透明化并并入客户区,右上角的最小化 / 最大化 / 关闭按钮
142
- // 由 DWM 继续原生绘制,标题文字置空。
143
- m := margins{cxLeftWidth: 0, cxRightWidth: 0, cyTopHeight: 0, cyBottomHeight: 1}
144
- procDwmExtendFrameIntoArea.Call(hwnd, uintptr(unsafe.Pointer(&m)))
145
- // 标题文字一并清除,标题栏区域只保留系统按钮
146
- procSetWindowText.Call(hwnd, uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(""))))
260
+ default: // TitleBarNative:补齐系统原生标题栏与可调边框。
261
+ // webview_go 底层创建的窗口默认 style 不含 WS_CAPTION(见 WebView2 窗口创建),
262
+ // 因此 native 模式必须显式补回标题栏 / 系统菜单 / 可调边框,
263
+ // 否则窗口会表现为无边框(无原生三按钮、不可拖拽调整大小)。
264
+ style := getWindowStyle(hwnd)
265
+ style |= wsCaption | wsSysMenu | wsThickFrame
266
+ setWindowStyle(hwnd, style)
147
267
  refreshFrame(hwnd)
148
- default: // TitleBarNative:不处理
149
268
  }
150
269
  }
270
+
271
+ // setWindowIcon 把 exe 内嵌的应用程序图标同步到窗口标题栏与任务栏:
272
+ // - native 模式:标题栏图标(ICON_SMALL)与任务栏 / Alt-Tab 图标(ICON_BIG)均来自 exe 图标,
273
+ // 保证「标题栏图标 = exe 图标」;
274
+ // - frameless 模式:无标题栏,但任务栏 / Alt-Tab 仍显示 exe 图标。
275
+ //
276
+ // 图标经 LoadImageW 从 PE 资源 RT_GROUP_ICON(ID=0) 加载(rcedit 注入的 group icon ID=0),
277
+ // 不依赖 resources 文件夹里的任何图标文件。
278
+ func (a *App) setWindowIcon() {
279
+ hwnd := a.WindowHandle()
280
+ if hwnd == 0 {
281
+ return
282
+ }
283
+ cxIcon, _, _ := procGetSystemMetrics.Call(smCXIcon)
284
+ cyIcon, _, _ := procGetSystemMetrics.Call(smCYIcon)
285
+ cxSmall, _, _ := procGetSystemMetrics.Call(smCXSmall)
286
+ cySmall, _, _ := procGetSystemMetrics.Call(smCYSmall)
287
+ big := loadExeIcon(cxIcon, cyIcon)
288
+ small := loadExeIcon(cxSmall, cySmall)
289
+ if big != 0 {
290
+ procSendMessage.Call(hwnd, wmSetIcon, 1 /* ICON_BIG */, big)
291
+ procDestroyIcon.Call(big)
292
+ }
293
+ if small != 0 {
294
+ procSendMessage.Call(hwnd, wmSetIcon, 0 /* ICON_SMALL */, small)
295
+ procDestroyIcon.Call(small)
296
+ }
297
+ }
298
+
299
+ // dibToPNG 将 ICO 内嵌的 DIB 图像(BITMAPINFOHEADER 起始的裸 DIB,即 rcedit 注入
300
+ // 非 PNG .ico 时的 RT_ICON 数据)纯 Go 解析为 PNG 字节,替代原 GDI
301
+ // CreateDIBSection+DrawIconEx 绘制路径(消除对 gdi32/user32 绘图 API 的依赖)。
302
+ // 支持 32/24 bpp;透明由 AND mask 决定(对应位=1 表示透明)。
303
+ func dibToPNG(data []byte) ([]byte, error) {
304
+ if len(data) < 40 {
305
+ return nil, fmt.Errorf("DIB too short: %d bytes", len(data))
306
+ }
307
+ biSize := binary.LittleEndian.Uint32(data[0:4])
308
+ if biSize < 40 {
309
+ return nil, fmt.Errorf("unsupported BITMAPINFOHEADER size %d", biSize)
310
+ }
311
+ width := int(binary.LittleEndian.Uint32(data[4:8]))
312
+ heightRaw := int32(binary.LittleEndian.Uint32(data[8:12]))
313
+ bitCount := binary.LittleEndian.Uint16(data[14:16])
314
+ if width <= 0 || heightRaw == 0 {
315
+ return nil, fmt.Errorf("bad dimensions %dx%d", width, heightRaw)
316
+ }
317
+ bpp := (int(bitCount) + 7) / 8 // bytes per pixel
318
+ if bpp != 3 && bpp != 4 {
319
+ return nil, fmt.Errorf("unsupported bitcount %d", bitCount)
320
+ }
321
+ height := int(heightRaw)
322
+ if height < 0 {
323
+ height = -height
324
+ }
325
+ // ICO 的 DIB 高度可能为实际像素高度的 2 倍(上方 XOR + 下方 AND mask),
326
+ // 此时需折半,否则图像会被纵向拉伸。
327
+ pixelRowBytes := (width*bpp + 3) &^ 3 // 每行按 4 字节对齐
328
+ andRowBytes := ((width + 31) / 32) * 4
329
+ pxLen := pixelRowBytes * height
330
+ if pxLen > len(data)-int(biSize) && height%2 == 0 {
331
+ height /= 2
332
+ pxLen = pixelRowBytes * height
333
+ }
334
+ pxStart := int(biSize)
335
+ andStart := pxStart + pxLen
336
+ hasAndMask := heightRaw > 0 // 正高度表示 DIB 末尾带 AND mask
337
+ if !hasAndMask {
338
+ hasAndMask = andStart+andRowBytes*height <= len(data)
339
+ }
340
+ img := image.NewRGBA(image.Rect(0, 0, width, height))
341
+ for y := 0; y < height; y++ {
342
+ srcY := height - 1 - y // DIB 自底向上:数据首行是图像末行
343
+ row := pxStart + srcY*pixelRowBytes
344
+ andRow := andStart + srcY*andRowBytes
345
+ for x := 0; x < width; x++ {
346
+ off := row + x*bpp
347
+ if off+bpp > len(data) {
348
+ return nil, fmt.Errorf("DIB data truncated at x=%d,y=%d", x, y)
349
+ }
350
+ b := data[off]
351
+ g := data[off+1]
352
+ r := data[off+2]
353
+ a := uint8(255)
354
+ if hasAndMask && (data[andRow+x/8]>>uint(7-x%8))&1 == 1 {
355
+ a = 0
356
+ }
357
+ img.SetRGBA(x, y, color.RGBA{r, g, b, a})
358
+ }
359
+ }
360
+ var buf bytes.Buffer
361
+ if err := png.Encode(&buf, img); err != nil {
362
+ return nil, err
363
+ }
364
+ return buf.Bytes(), nil
365
+ }
File without changes
File without changes
@@ -0,0 +1,62 @@
1
+ name: CI Pipeline
2
+ on: [push, pull_request]
3
+
4
+ jobs:
5
+ build:
6
+ runs-on: ${{ matrix.image }}
7
+ strategy:
8
+ fail-fast: false
9
+ matrix:
10
+ # Go 1.23 was the latest version as of 2024-08-31 but the action output a "warning":
11
+ # Failed to restore: "/usr/bin/tar" failed with error: The process '/usr/bin/tar' failed with exit code 2
12
+ # Go 1.22 didn't output the above "warning" so we're using this version.
13
+ # Go 1.14 made -mod=vendor default.
14
+ # Go 1.13 is the version set in go.mod.
15
+ include:
16
+ - { image: macos-14, go: '1.22' }
17
+ - { image: macos-14, go: '1.21' }
18
+ - { image: macos-14, go: '1.20' }
19
+ # Go 1.19 is the earliest version available for ARM64.
20
+ - { image: macos-14, go: '1.19' }
21
+ # macos-12 runner has x86_64 support which is needed for old versions of Go
22
+ - { image: macos-12, go: '1.18' }
23
+ - { image: macos-12, go: '1.17' }
24
+ - { image: macos-12, go: '1.16' }
25
+ - { image: macos-12, go: '1.15' }
26
+ - { image: macos-12, go: '1.14' }
27
+ - { image: macos-12, go: '1.13' }
28
+ - { image: ubuntu-22.04, go: '1.22', apt: libgtk-4-dev libwebkitgtk-6.0-dev }
29
+ - { image: ubuntu-22.04, go: '1.22', apt: libgtk-3-dev libwebkit2gtk-4.1-dev }
30
+ - { image: ubuntu-22.04, go: '1.22', apt: libgtk-3-dev libwebkit2gtk-4.0-dev }
31
+ - { image: ubuntu-22.04, go: '1.21', apt: libgtk-3-dev libwebkit2gtk-4.1-dev }
32
+ - { image: ubuntu-22.04, go: '1.20', apt: libgtk-3-dev libwebkit2gtk-4.1-dev }
33
+ - { image: ubuntu-22.04, go: '1.19', apt: libgtk-3-dev libwebkit2gtk-4.1-dev }
34
+ - { image: ubuntu-22.04, go: '1.18', apt: libgtk-3-dev libwebkit2gtk-4.1-dev }
35
+ - { image: ubuntu-22.04, go: '1.17', apt: libgtk-3-dev libwebkit2gtk-4.1-dev }
36
+ - { image: ubuntu-22.04, go: '1.16', apt: libgtk-3-dev libwebkit2gtk-4.1-dev }
37
+ - { image: ubuntu-22.04, go: '1.15', apt: libgtk-3-dev libwebkit2gtk-4.1-dev }
38
+ - { image: ubuntu-22.04, go: '1.14', apt: libgtk-3-dev libwebkit2gtk-4.1-dev }
39
+ - { image: ubuntu-22.04, go: '1.13', apt: libgtk-3-dev libwebkit2gtk-4.1-dev }
40
+ - { image: windows-2022, go: '1.22' }
41
+ - { image: windows-2022, go: '1.21' }
42
+ # Go 1.20 is the earliest version that is usable in this environment as of 2024-08-31.
43
+ # Compilation fails with older versions:
44
+ # [...]/bin/ld.exe: [...]\go-link-3209855222\000008.o: in function `x_cgo_thread_start':
45
+ # \\_\_\runtime\cgo/gcc_util.c:18: undefined reference to `__imp___iob_func'
46
+ - { image: windows-2022, go: '1.20' }
47
+ name: Build (${{ matrix.image }}, go ${{ matrix.go }})
48
+ steps:
49
+ - uses: actions/checkout@v4
50
+ - name: Install dependencies
51
+ if: runner.os == 'Linux'
52
+ run: sudo apt-get update && sudo apt-get install -y libwebkit2gtk-4.0-dev
53
+ - uses: actions/setup-go@v5
54
+ with:
55
+ go-version: ${{ matrix.go }}
56
+ - name: Build examples
57
+ run: >
58
+ go build
59
+ ./examples/basic
60
+ ./examples/bind
61
+ - name: Run tests
62
+ run: go test
@@ -0,0 +1,15 @@
1
+ # Changelog
2
+
3
+ ### Migrating from v0.1.1 to v0.10.0
4
+
5
+ 1. `Webview.Open()` has been removed. Use other webview APIs to create a window, open a link and run main UI loop.
6
+ 2. `Webview.Debug()` and `webview.Debugf()` have been removed. Use your favorite logging library to debug webview apps.
7
+ 3. `Webview.Settings` struct has been removed. Title, URL and size are controlled via other API setters and can be updated at any time, not only when webview is created.
8
+ 4. `Webview.Loop()` has been removed. Use `Run()` instead.
9
+ 5. `WebView.Run()`, `WebView.Terminate()`, `WebView.SetTitle()`, `WebView.Dispatch()` stayed the same.
10
+ 6. `WebView.Exit()` has been renamed to `WebView.Destroy()`
11
+ 7. `WebView.SetColor()` and `WebView.SetFullScreen()` have been removed. Use `Window()` to get native window handle and probably write some Cgo code to adjust native window to your taste.
12
+ 8. `Webview.Dialog` has been removed. But it is likely to be brought back as a standalone module.
13
+ 9. `WebView.Eval()` remained the same.
14
+ 10. `WebView.InjectCSS()` has been removed. Use eval to inject style tag with CSS inside.
15
+ 11. `WebView.Bind()` kept the name, but changed the semantics. Only functions can be bound. Not the structs, like in Lorca.
@@ -0,0 +1,22 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2017 Serge Zaitsev
4
+ Copyright (c) 2020 webview
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ of this software and associated documentation files (the "Software"), to deal
8
+ in the Software without restriction, including without limitation the rights
9
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ copies of the Software, and to permit persons to whom the Software is
11
+ furnished to do so, subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in all
14
+ copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ SOFTWARE.
@@ -0,0 +1,50 @@
1
+ # webview_go
2
+
3
+ [![GoDoc](https://godoc.org/github.com/webview/webview_go?status.svg)](https://godoc.org/github.com/webview/webview_go)
4
+ [![Go Report Card](https://goreportcard.com/badge/github.com/webview/webview_go)](https://goreportcard.com/report/github.com/webview/webview_go)
5
+
6
+ Go language binding for the [webview library][webview].
7
+
8
+ > [!NOTE]
9
+ > Versions <= 0.1.1 are available in the [old repository][webview].
10
+
11
+ ### Getting Started
12
+
13
+ See [Go package documentation][go-docs] for the Go API documentation, or simply read the source code.
14
+
15
+ Start with creating a new directory structure for your project.
16
+
17
+ ```sh
18
+ mkdir my-project && cd my-project
19
+ ```
20
+
21
+ Create a new Go module.
22
+
23
+ ```sh
24
+ go mod init example.com/app
25
+ ```
26
+
27
+ Save one of the example programs into your project directory.
28
+
29
+ ```sh
30
+ curl -sSLo main.go "https://raw.githubusercontent.com/webview/webview_go/master/examples/basic/main.go"
31
+ ```
32
+
33
+ Install dependencies.
34
+
35
+ ```sh
36
+ go get github.com/webview/webview_go
37
+ ```
38
+
39
+ Build the example. On Windows, add `-ldflags="-H windowsgui"` to the command line.
40
+
41
+ ```sh
42
+ go build
43
+ ```
44
+
45
+ ### Notes
46
+
47
+ Calling `Eval()` or `Dispatch()` before `Run()` does not work because the webview instance has only been configured and not yet started.
48
+
49
+ [go-docs]: https://pkg.go.dev/github.com/webview/webview_go
50
+ [webview]: https://github.com/webview/webview
@@ -0,0 +1,12 @@
1
+ package main
2
+
3
+ import webview "github.com/webview/webview_go"
4
+
5
+ func main() {
6
+ w := webview.New(false)
7
+ defer w.Destroy()
8
+ w.SetTitle("Basic Example")
9
+ w.SetSize(480, 320, webview.HintNone)
10
+ w.SetHtml("Thanks for using webview!")
11
+ w.Run()
12
+ }
@@ -0,0 +1,38 @@
1
+ package main
2
+
3
+ import webview "github.com/webview/webview_go"
4
+
5
+ const html = `<button id="increment">Tap me</button>
6
+ <div>You tapped <span id="count">0</span> time(s).</div>
7
+ <script>
8
+ const [incrementElement, countElement] =
9
+ document.querySelectorAll("#increment, #count");
10
+ document.addEventListener("DOMContentLoaded", () => {
11
+ incrementElement.addEventListener("click", () => {
12
+ window.increment().then(result => {
13
+ countElement.textContent = result.count;
14
+ });
15
+ });
16
+ });
17
+ </script>`
18
+
19
+ type IncrementResult struct {
20
+ Count uint `json:"count"`
21
+ }
22
+
23
+ func main() {
24
+ var count uint = 0
25
+ w := webview.New(false)
26
+ defer w.Destroy()
27
+ w.SetTitle("Bind Example")
28
+ w.SetSize(480, 320, webview.HintNone)
29
+
30
+ // A binding that increments a value and immediately returns the new value.
31
+ w.Bind("increment", func() IncrementResult {
32
+ count++
33
+ return IncrementResult{Count: count}
34
+ })
35
+
36
+ w.SetHtml(html)
37
+ w.Run()
38
+ }
@@ -0,0 +1,36 @@
1
+ #include "webview.h"
2
+
3
+ #include <stdlib.h>
4
+ #include <stdint.h>
5
+
6
+ struct binding_context {
7
+ webview_t w;
8
+ uintptr_t index;
9
+ };
10
+
11
+ void _webviewDispatchGoCallback(void *);
12
+ void _webviewBindingGoCallback(webview_t, char *, char *, uintptr_t);
13
+
14
+ static void _webview_dispatch_cb(webview_t w, void *arg) {
15
+ _webviewDispatchGoCallback(arg);
16
+ }
17
+
18
+ static void _webview_binding_cb(const char *id, const char *req, void *arg) {
19
+ struct binding_context *ctx = (struct binding_context *) arg;
20
+ _webviewBindingGoCallback(ctx->w, (char *)id, (char *)req, ctx->index);
21
+ }
22
+
23
+ void CgoWebViewDispatch(webview_t w, uintptr_t arg) {
24
+ webview_dispatch(w, _webview_dispatch_cb, (void *)arg);
25
+ }
26
+
27
+ void CgoWebViewBind(webview_t w, const char *name, uintptr_t index) {
28
+ struct binding_context *ctx = calloc(1, sizeof(struct binding_context));
29
+ ctx->w = w;
30
+ ctx->index = index;
31
+ webview_bind(w, name, _webview_binding_cb, (void *)ctx);
32
+ }
33
+
34
+ void CgoWebViewUnbind(webview_t w, const char *name) {
35
+ webview_unbind(w, name);
36
+ }
@@ -0,0 +1,3 @@
1
+ module github.com/webview/webview_go
2
+
3
+ go 1.13
File without changes
@@ -0,0 +1,27 @@
1
+ Copyright (C) Microsoft Corporation. All rights reserved.
2
+
3
+ Redistribution and use in source and binary forms, with or without
4
+ modification, are permitted provided that the following conditions are
5
+ met:
6
+
7
+ * Redistributions of source code must retain the above copyright
8
+ notice, this list of conditions and the following disclaimer.
9
+ * Redistributions in binary form must reproduce the above
10
+ copyright notice, this list of conditions and the following disclaimer
11
+ in the documentation and/or other materials provided with the
12
+ distribution.
13
+ * The name of Microsoft Corporation, or the names of its contributors
14
+ may not be used to endorse or promote products derived from this
15
+ software without specific prior written permission.
16
+
17
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.