5
0
mirror of https://github.com/wailsapp/wails.git synced 2025-05-10 22:19:46 +08:00

Merge branch 'master' into v3-alpha

# Conflicts:
#	v2/internal/frontend/desktop/windows/go-webview2/webviewloader/env_create.go
This commit is contained in:
Lea Anthony 2023-08-14 18:08:52 +10:00
commit ee8eb001c2
No known key found for this signature in database
GPG Key ID: 33DAF7BB90A58405
158 changed files with 1832 additions and 6181 deletions

View File

@ -7,7 +7,7 @@ body:
- type: markdown - type: markdown
attributes: attributes:
value: | value: |
***Please note: No new bug reports are being accepted for Wails v1*** ***Please note: No bug reports are currently being accepted for Wails v3***
Before submitting this issue, please do the following: Before submitting this issue, please do the following:
- Do a web search for your error. This usually leads to a much better understanding of the issue. - Do a web search for your error. This usually leads to a much better understanding of the issue.
- Prove that the error is indeed a Wails bug and not an application bug, with a specific set of steps to reproduce. - Prove that the error is indeed a Wails bug and not an application bug, with a specific set of steps to reproduce.
@ -84,4 +84,4 @@ body:
description: Add any other context about the problem here. description: Add any other context about the problem here.
placeholder: Add any other context about the problem here. placeholder: Add any other context about the problem here.
validations: validations:
required: false required: false

View File

@ -1,37 +0,0 @@
name: Format Markdown Files
on:
workflow_dispatch:
push:
branches: [master]
jobs:
format_markdown_files:
runs-on: ubuntu-latest
if: github.repository == 'wailsapp/wails'
steps:
- uses: actions/checkout@v3
- name: Setup Nodejs
uses: actions/setup-node@v2
with:
node-version: 18.x
- name: Install Task
uses: arduino/setup-task@v1
with:
version: 3.x
repo-token: ${{ secrets.GITHUB_TOKEN }}
- name: Format All Markdown Files
run: task format-all-md
- name: Create Pull Request
uses: peter-evans/create-pull-request@v4
with:
commit-message: "docs: format document"
title: "docs: format document"
body: "- [x] Format all Markdown(x) documents"
branch: chore/format-markdown-files
delete-branch: true
draft: false

167
README.es.md Normal file
View File

@ -0,0 +1,167 @@
<p align="center" style="text-align: center">
<img src="./assets/images/logo-universal.png" width="55%"><br/>
</p>
<p align="center">
Construye aplicaciones de escritorio usando Go y tecnologías web.
<br/>
<br/>
<a href="https://github.com/wailsapp/wails/blob/master/LICENSE">
<img alt="GitHub" src="https://img.shields.io/github/license/wailsapp/wails"/>
</a>
<a href="https://goreportcard.com/report/github.com/wailsapp/wails">
<img src="https://goreportcard.com/badge/github.com/wailsapp/wails" />
</a>
<a href="https://pkg.go.dev/github.com/wailsapp/wails">
<img src="https://pkg.go.dev/badge/github.com/wailsapp/wails.svg" alt="Go Reference"/>
</a>
<a href="https://github.com/wailsapp/wails/issues">
<img src="https://img.shields.io/badge/contributions-welcome-brightgreen.svg?style=flat" alt="CodeFactor" />
</a>
<a href="https://app.fossa.com/projects/git%2Bgithub.com%2Fwailsapp%2Fwails?ref=badge_shield" alt="FOSSA Status">
<img src="https://app.fossa.com/api/projects/git%2Bgithub.com%2Fwailsapp%2Fwails.svg?type=shield" />
</a>
<a href="https://github.com/avelino/awesome-go" rel="nofollow">
<img src="https://cdn.rawgit.com/sindresorhus/awesome/d7305f38d29fed78fa85652e3a63e154dd8e8829/media/badge.svg" alt="Awesome" />
</a>
<a href="https://discord.gg/BrRSWTaxVK">
<img alt="Discord" src="https://dcbadge.vercel.app/api/server/BrRSWTaxVK?style=flat"/>
</a>
<br/>
<a href="https://github.com/wailsapp/wails/actions/workflows/build-and-test.yml" rel="nofollow">
<img src="https://img.shields.io/github/actions/workflow/status/wailsapp/wails/build-and-test.yml?branch=master&logo=Github" alt="Build" />
</a>
<a href="https://github.com/wailsapp/wails/tags" rel="nofollow">
<img alt="GitHub tag (latest SemVer pre-release)" src="https://img.shields.io/github/v/tag/wailsapp/wails?include_prereleases&label=version"/>
</a>
</p>
<div align="center">
<strong>
<samp>
[English](README.md) · [简体中文](README.zh-Hans.md) · [日本語](README.ja.md) ·
[한국어](README.ko.md) · [Español](README.es.md)
</samp>
</strong>
</div>
## Tabla de Contenidos
- [Tabla de Contenidos](#tabla-de-contenidos)
- [Introducción](#introducción)
- [Funcionalidades](#funcionalidades)
- [Plan de Trabajo](#plan-de-trabajo)
- [Empezando](#empezando)
- [Patrocinadores](#patrocinadores)
- [Preguntas Frecuentes](#preguntas-frecuentes)
- [Estrellas a lo Largo del Tiempo](#estrellas-a-lo-largo-del-tiempo)
- [Colaboradores](#colaboradores)
- [Licencia](#licencia)
- [Inspiración](#inspiración)
## Introducción
El método tradicional para proveer una interfaz web en programas hechos con Go
es a través del servidor web incorporado. Wails ofrece un enfoque diferente al
permitir combinar el código hecho en Go con un frontend web en un solo archivo
binario. Las herramientas que proporcionamos facilitan este trabajo para ti, al
crear, compilar y empaquetar tu proyecto. ¡Lo único que debes hacer es ponerte
creativo!
## Funcionalidades
- Utiliza Go estándar para el backend
- Utiliza cualquier tecnología frontend con la que ya estés familiarizado para
construir tu interfaz de usuario
- Crea rápidamente interfaces de usuario enriquecidas para tus programas en Go
utilizando plantillas predefinidas
- Invoca fácilmente métodos de Go desde Javascript
- Definiciones de Typescript generadas automáticamente para tus structs y
métodos de Go
- Diálogos y menús nativos
- Soporte nativo de modo oscuro / claro
- Soporte de translucidez y efectos de ventana esmerilada
- Sistema de eventos unificado entre Go y Javascript
- Herramienta CLI potente para generar y construir tus proyectos rápidamente
- Multiplataforma
- Usa motores de renderizado nativos - ¡_sin navegador integrado_!
### Plan de Trabajo
El plan de trabajo se puede encontrar
[aqui](https://github.com/wailsapp/wails/discussions/1484). Por favor,
consúltalo antes de abrir una solicitud de mejora.
## Empezando
Las instrucciones de instalacion se encuentran en nuestra
[pagina web oficial](https://wails.io/docs/gettingstarted/installation).
## Patrocinadores
Este Proyecto cuenta con el apoyo de estas amables personas/ compañías:
<img src="website/static/img/sponsors.svg" style="width:100%;max-width:800px;"/>
<p align="center">
<img src="https://wails.io/img/sponsor/jetbrains-grayscale.webp" style="width: 100px"/>
</p>
## Preguntas Frecuentes
- ¿Es esta una alternativa a Electron?
Depende de tus requisitos. Está diseñado para facilitar a los programadores de
Go la creación de aplicaciones de escritorio livianas o agregar una interfaz
gráfica a sus aplicaciones existentes. Wails ofrece elementos nativos como
menús y diálogos, por lo que podría considerarse una alternativa liviana a
Electron.
- ¿A quien esta dirigido este proyecto?
El proyecto esta dirigido a programadores de Go que desean integrar una
interfaz HMTL/JS/CSS en sus aplicaciones, sin tener que recurrir a la creación
de un servidor y abrir el navegador para visualizarla.
- ¿Cual es el significado del nombre?
Cuando vi WebView, pensé: "Lo que realmente quiero es una herramienta para
construir una aplicación WebView, algo similar a lo que Rails es para Ruby".
Así que inicialmente fue un juego de palabras (WebView en Rails). Además, por
casualidad, también es homófono del nombre en inglés del
[país](https://en.wikipedia.org/wiki/Wales) del que provengo. Así que se quedó
con ese nombre.
## Estrellas a lo Largo del Tiempo
[![Star History Chart](https://api.star-history.com/svg?repos=wailsapp/wails&type=Date)](https://star-history.com/#wailsapp/wails&Date)
## Colaboradores
¡La lista de colaboradores se está volviendo demasiado grande para el archivo
readme! Todas las personas increíbles que han contribuido a este proyecto tienen
su propia página [aqui](https://wails.io/credits#contributors).
## Licencia
[![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fwailsapp%2Fwails.svg?type=large)](https://app.fossa.com/projects/git%2Bgithub.com%2Fwailsapp%2Fwails?ref=badge_large)
## Inspiración
Este proyecto fue construido mientras se escuchaban estos álbumes:
- [Manic Street Preachers - Resistance Is Futile](https://open.spotify.com/album/1R2rsEUqXjIvAbzM0yHrxA)
- [Manic Street Preachers - This Is My Truth, Tell Me Yours](https://open.spotify.com/album/4VzCL9kjhgGQeKCiojK1YN)
- [The Midnight - Endless Summer](https://open.spotify.com/album/4Krg8zvprquh7TVn9OxZn8)
- [Gary Newman - Savage (Songs from a Broken World)](https://open.spotify.com/album/3kMfsD07Q32HRWKRrpcexr)
- [Steve Vai - Passion & Warfare](https://open.spotify.com/album/0oL0OhrE2rYVns4IGj8h2m)
- [Ben Howard - Every Kingdom](https://open.spotify.com/album/1nJsbWm3Yy2DW1KIc1OKle)
- [Ben Howard - Noonday Dream](https://open.spotify.com/album/6astw05cTiXEc2OvyByaPs)
- [Adwaith - Melyn](https://open.spotify.com/album/2vBE40Rp60tl7rNqIZjaXM)
- [Gwidaith Hen Fran - Cedors Hen Wrach](https://open.spotify.com/album/3v2hrfNGINPLuDP0YDTOjm)
- [Metallica - Metallica](https://open.spotify.com/album/2Kh43m04B1UkVcpcRa1Zug)
- [Bloc Party - Silent Alarm](https://open.spotify.com/album/6SsIdN05HQg2GwYLfXuzLB)
- [Maxthor - Another World](https://open.spotify.com/album/3tklE2Fgw1hCIUstIwPBJF)
- [Alun Tan Lan - Y Distawrwydd](https://open.spotify.com/album/0c32OywcLpdJCWWMC6vB8v)
[Alun Tan Lan - Y Distawrwydd](https://open.spotify.com/album/0c32OywcLpdJCWWMC6vB8v)

View File

@ -42,7 +42,8 @@
<strong> <strong>
<samp> <samp>
[English](README.md) · [简体中文](README.zh-Hans.md) · [日本語](README.ja.md) · [한국어](README.ko.md) [English](README.md) · [简体中文](README.zh-Hans.md) · [日本語](README.ja.md) ·
[한국어](README.ko.md) · [Español](README.es.md)
</samp> </samp>
</strong> </strong>

View File

@ -42,7 +42,8 @@
<strong> <strong>
<samp> <samp>
[English](README.md) · [简体中文](README.zh-Hans.md) · [日本語](README.ja.md) · [한국어](README.ko.md) [English](README.md) · [简体中文](README.zh-Hans.md) · [日本語](README.ja.md) ·
[한국어](README.ko.md) · [Español](README.es.md)
</samp> </samp>
</strong> </strong>

View File

@ -40,7 +40,8 @@
<strong> <strong>
<samp> <samp>
[English](README.md) · [简体中文](README.zh-Hans.md) · [日本語](README.ja.md) · [한국어](README.ko.md) [English](README.md) · [简体中文](README.zh-Hans.md) · [日本語](README.ja.md) ·
[한국어](README.ko.md) · [Español](README.es.md)
</samp> </samp>
</strong> </strong>

View File

@ -42,7 +42,8 @@
<strong> <strong>
<samp> <samp>
[English](README.md) · [简体中文](README.zh-Hans.md) · [日本語](README.ja.md) · [한국어](README.ko.md) [English](README.md) · [简体中文](README.zh-Hans.md) · [日本語](README.ja.md) ·
[한국어](README.ko.md) · [Español](README.es.md)
</samp> </samp>
</strong> </strong>
@ -87,7 +88,7 @@
## 快速入门 ## 快速入门
使用说明在 [官网](https://wails.io/docs/gettingstarted/installation)。 使用说明在 [官网](https://wails.io/zh-Hans/docs/gettingstarted/installation/)。
## 赞助商 ## 赞助商

View File

@ -13,9 +13,12 @@
} }
}, },
"node_modules/@antfu/utils": { "node_modules/@antfu/utils": {
"version": "0.5.2", "version": "0.7.4",
"resolved": "https://registry.npmmirror.com/@antfu/utils/-/utils-0.5.2.tgz", "resolved": "https://registry.npmjs.org/@antfu/utils/-/utils-0.7.4.tgz",
"integrity": "sha512-CQkeV+oJxUazwjlHD0/3ZD08QWKuGQkhnrKo3e6ly5pd48VUpXbb77q0xMU4+vc2CkJnDS02Eq/M9ugyX20XZA==" "integrity": "sha512-qe8Nmh9rYI/HIspLSTwtbMFPj6dISG6+dJnOguTlPNXtCvS2uezdxscVBb7/3DrmNbQK49TDqpkSQ1chbRGdpQ==",
"funding": {
"url": "https://github.com/sponsors/antfu"
}
}, },
"node_modules/ajv": { "node_modules/ajv": {
"version": "6.12.6", "version": "6.12.6",
@ -419,9 +422,9 @@
} }
}, },
"node_modules/defu": { "node_modules/defu": {
"version": "6.1.1", "version": "6.1.2",
"resolved": "https://registry.npmmirror.com/defu/-/defu-6.1.1.tgz", "resolved": "https://registry.npmjs.org/defu/-/defu-6.1.2.tgz",
"integrity": "sha512-aA964RUCsBt0FGoNIlA3uFgo2hO+WWC0fiC6DBps/0SFzkKcYoM/3CzVLIa5xSsrFjdioMdYgAIbwo80qp2MoA==" "integrity": "sha512-+uO4+qr7msjNNWKYPHqN/3+Dx3NFkmIzayk2L1MyZQlvgZb/J1A0fo410dpKrN2SnqFjt8n4JL8fDJE0wIgjFQ=="
}, },
"node_modules/delayed-stream": { "node_modules/delayed-stream": {
"version": "1.0.0", "version": "1.0.0",
@ -951,9 +954,9 @@
"integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==" "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g=="
}, },
"node_modules/jiti": { "node_modules/jiti": {
"version": "1.16.0", "version": "1.18.2",
"resolved": "https://registry.npmmirror.com/jiti/-/jiti-1.16.0.tgz", "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.18.2.tgz",
"integrity": "sha512-L3BJStEf5NAqNuzrpfbN71dp43mYIcBUlCRea/vdyv5dW/AYa1d4bpelko4SHdY3I6eN9Wzyasxirj1/vv5kmg==", "integrity": "sha512-QAdOptna2NYiSSpv0O/BwoHBSmz4YhpzJHyi+fnMRTXFjp7B8i/YG5Z8IfusxB1ufjcD2Sre1F3R+nX3fvy7gg==",
"bin": { "bin": {
"jiti": "bin/jiti.js" "jiti": "bin/jiti.js"
} }
@ -1443,9 +1446,9 @@
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
}, },
"node_modules/semver": { "node_modules/semver": {
"version": "7.3.8", "version": "7.5.3",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.3.tgz",
"integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", "integrity": "sha512-QBlUtyVk/5EeHbi7X0fw6liDZc7BBmEaSYn01fMU1OUYbf6GPsbTtd8WmnqbI20SeycoHSeiybkE/q1Q+qlThQ==",
"dependencies": { "dependencies": {
"lru-cache": "^6.0.0" "lru-cache": "^6.0.0"
}, },
@ -1765,13 +1768,16 @@
"integrity": "sha512-fk6CmUgwKCfX79EzcDQQpSCMxrHstvbLswFChHS0Vump+kFkw7nJBfTZoC1j0bOGoY9I7R3n2DGek5ajbcYnOw==" "integrity": "sha512-fk6CmUgwKCfX79EzcDQQpSCMxrHstvbLswFChHS0Vump+kFkw7nJBfTZoC1j0bOGoY9I7R3n2DGek5ajbcYnOw=="
}, },
"node_modules/unconfig": { "node_modules/unconfig": {
"version": "0.3.7", "version": "0.3.9",
"resolved": "https://registry.npmmirror.com/unconfig/-/unconfig-0.3.7.tgz", "resolved": "https://registry.npmjs.org/unconfig/-/unconfig-0.3.9.tgz",
"integrity": "sha512-1589b7oGa8ILBYpta7TndM5mLHLzHUqBfhszeZxuUBrjO/RoQ52VGVWsS3w0C0GLNxO9RPmqkf6BmIvBApaRdA==", "integrity": "sha512-8yhetFd48M641mxrkWA+C/lZU4N0rCOdlo3dFsyFPnBHBjMJfjT/3eAZBRT2RxCRqeBMAKBVgikejdS6yeBjMw==",
"dependencies": { "dependencies": {
"@antfu/utils": "^0.5.2", "@antfu/utils": "^0.7.2",
"defu": "^6.1.0", "defu": "^6.1.2",
"jiti": "^1.16.0" "jiti": "^1.18.2"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
} }
}, },
"node_modules/undici": { "node_modules/undici": {

View File

@ -57,6 +57,7 @@ func buildApplication(f *flags.Build) error {
OutputFile: f.OutputFilename, OutputFile: f.OutputFilename,
CleanBinDirectory: f.Clean, CleanBinDirectory: f.Clean,
Mode: f.GetBuildMode(), Mode: f.GetBuildMode(),
Devtools: f.Debug || f.Devtools,
Pack: !f.NoPackage, Pack: !f.NoPackage,
LDFlags: f.LdFlags, LDFlags: f.LdFlags,
Compiler: f.Compiler, Compiler: f.Compiler,
@ -82,6 +83,7 @@ func buildApplication(f *flags.Build) error {
{"Compiler", f.GetCompilerPath()}, {"Compiler", f.GetCompilerPath()},
{"Skip Bindings", bool2Str(f.SkipBindings)}, {"Skip Bindings", bool2Str(f.SkipBindings)},
{"Build Mode", f.GetBuildModeAsString()}, {"Build Mode", f.GetBuildModeAsString()},
{"Devtools", bool2Str(buildOptions.Devtools)},
{"Frontend Directory", projectOptions.GetFrontendDir()}, {"Frontend Directory", projectOptions.GetFrontendDir()},
{"Obfuscated", bool2Str(f.Obfuscated)}, {"Obfuscated", bool2Str(f.Obfuscated)},
} }

View File

@ -35,6 +35,7 @@ type Build struct {
ForceBuild bool `name:"f" description:"Force build of application"` ForceBuild bool `name:"f" description:"Force build of application"`
UpdateWailsVersionGoMod bool `name:"u" description:"Updates go.mod to use the same Wails version as the CLI"` UpdateWailsVersionGoMod bool `name:"u" description:"Updates go.mod to use the same Wails version as the CLI"`
Debug bool `description:"Builds the application in debug mode"` Debug bool `description:"Builds the application in debug mode"`
Devtools bool `description:"Enable Devtools in productions, Already enabled in debug mode (-debug)"`
NSIS bool `description:"Generate NSIS installer for Windows"` NSIS bool `description:"Generate NSIS installer for Windows"`
TrimPath bool `description:"Remove all file system paths from the resulting executable"` TrimPath bool `description:"Remove all file system paths from the resulting executable"`
WindowsConsole bool `description:"Keep the console when building for Windows"` WindowsConsole bool `description:"Keep the console when building for Windows"`

View File

@ -120,6 +120,7 @@ func (d *Dev) GenerateBuildOptions() *build.Options {
result := &build.Options{ result := &build.Options{
OutputType: "dev", OutputType: "dev",
Mode: build.Dev, Mode: build.Dev,
Devtools: true,
Arch: runtime.GOARCH, Arch: runtime.GOARCH,
Pack: true, Pack: true,
Platform: runtime.GOOS, Platform: runtime.GOOS,

View File

@ -45,6 +45,9 @@ VIAddVersionKey "FileVersion" "${INFO_PRODUCTVERSION}"
VIAddVersionKey "LegalCopyright" "${INFO_COPYRIGHT}" VIAddVersionKey "LegalCopyright" "${INFO_COPYRIGHT}"
VIAddVersionKey "ProductName" "${INFO_PRODUCTNAME}" VIAddVersionKey "ProductName" "${INFO_PRODUCTNAME}"
# Enable HiDPI support. https://nsis.sourceforge.io/Reference/ManifestDPIAware
ManifestDPIAware true
!include "MUI.nsh" !include "MUI.nsh"
!define MUI_ICON "..\icon.ico" !define MUI_ICON "..\icon.ico"

View File

@ -13,33 +13,33 @@ require (
github.com/go-git/go-git/v5 v5.3.0 github.com/go-git/go-git/v5 v5.3.0
github.com/go-ole/go-ole v1.2.6 github.com/go-ole/go-ole v1.2.6
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510
github.com/google/uuid v1.1.2 github.com/google/uuid v1.3.0
github.com/jackmordaunt/icns v1.0.0 github.com/jackmordaunt/icns v1.0.0
github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e github.com/labstack/echo/v4 v4.10.2
github.com/labstack/echo/v4 v4.9.0 github.com/labstack/gommon v0.4.0
github.com/labstack/gommon v0.3.1
github.com/leaanthony/clir v1.3.0 github.com/leaanthony/clir v1.3.0
github.com/leaanthony/debme v1.2.1 github.com/leaanthony/debme v1.2.1
github.com/leaanthony/go-ansi-parser v1.0.1 github.com/leaanthony/go-ansi-parser v1.6.0
github.com/leaanthony/gosod v1.0.3 github.com/leaanthony/gosod v1.0.3
github.com/leaanthony/slicer v1.5.0 github.com/leaanthony/slicer v1.6.0
github.com/leaanthony/winicon v1.0.0 github.com/leaanthony/winicon v1.0.0
github.com/matryer/is v1.4.0 github.com/matryer/is v1.4.0
github.com/pkg/browser v0.0.0-20210706143420-7d21f8c997e2 github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8
github.com/pkg/errors v0.9.1 github.com/pkg/errors v0.9.1
github.com/pterm/pterm v0.12.49 github.com/pterm/pterm v0.12.49
github.com/sabhiram/go-gitignore v0.0.0-20210923224102-525f6e181f06 github.com/sabhiram/go-gitignore v0.0.0-20210923224102-525f6e181f06
github.com/samber/lo v1.27.1 github.com/samber/lo v1.38.1
github.com/stretchr/testify v1.8.0 github.com/stretchr/testify v1.8.1
github.com/tc-hib/winres v0.1.5 github.com/tc-hib/winres v0.1.5
github.com/tidwall/sjson v1.1.7 github.com/tidwall/sjson v1.1.7
github.com/tkrajina/go-reflector v0.5.5 github.com/tkrajina/go-reflector v0.5.6
github.com/wailsapp/go-webview2 v1.0.1
github.com/wailsapp/mimetype v1.4.1 github.com/wailsapp/mimetype v1.4.1
github.com/wzshiming/ctc v1.2.3 github.com/wzshiming/ctc v1.2.3
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 golang.org/x/mod v0.8.0
golang.org/x/net v0.7.0 golang.org/x/net v0.10.0
golang.org/x/sys v0.5.0 golang.org/x/sys v0.8.0
golang.org/x/tools v0.1.12 golang.org/x/tools v0.6.0
) )
require ( require (
@ -59,12 +59,13 @@ require (
github.com/gorilla/css v1.0.0 // indirect github.com/gorilla/css v1.0.0 // indirect
github.com/imdario/mergo v0.3.12 // indirect github.com/imdario/mergo v0.3.12 // indirect
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e // indirect
github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351 // indirect github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351 // indirect
github.com/kr/pretty v0.3.0 // indirect github.com/kr/pretty v0.3.0 // indirect
github.com/lithammer/fuzzysearch v1.1.5 // indirect github.com/lithammer/fuzzysearch v1.1.5 // indirect
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
github.com/mattn/go-colorable v0.1.11 // indirect github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.14 // indirect github.com/mattn/go-isatty v0.0.19 // indirect
github.com/mattn/go-runewidth v0.0.13 // indirect github.com/mattn/go-runewidth v0.0.13 // indirect
github.com/microcosm-cc/bluemonday v1.0.17 // indirect github.com/microcosm-cc/bluemonday v1.0.17 // indirect
github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect
@ -73,23 +74,23 @@ require (
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // indirect github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // indirect
github.com/olekukonko/tablewriter v0.0.5 // indirect github.com/olekukonko/tablewriter v0.0.5 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/rivo/uniseg v0.2.0 // indirect github.com/rivo/uniseg v0.4.4 // indirect
github.com/sergi/go-diff v1.2.0 // indirect github.com/sergi/go-diff v1.2.0 // indirect
github.com/tidwall/gjson v1.9.3 // indirect github.com/tidwall/gjson v1.9.3 // indirect
github.com/tidwall/match v1.1.1 // indirect github.com/tidwall/match v1.1.1 // indirect
github.com/tidwall/pretty v1.2.0 // indirect github.com/tidwall/pretty v1.2.0 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/valyala/fasttemplate v1.2.1 // indirect github.com/valyala/fasttemplate v1.2.2 // indirect
github.com/wzshiming/winseq v0.0.0-20200112104235-db357dc107ae // indirect github.com/wzshiming/winseq v0.0.0-20200112104235-db357dc107ae // indirect
github.com/xanzy/ssh-agent v0.3.0 // indirect github.com/xanzy/ssh-agent v0.3.0 // indirect
github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 // indirect github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 // indirect
github.com/yuin/goldmark v1.4.13 // indirect github.com/yuin/goldmark v1.4.13 // indirect
github.com/yuin/goldmark-emoji v1.0.1 // indirect github.com/yuin/goldmark-emoji v1.0.1 // indirect
golang.org/x/crypto v0.1.0 // indirect golang.org/x/crypto v0.9.0 // indirect
golang.org/x/exp v0.0.0-20220303212507-bbda1eaf7a17 // indirect golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 // indirect
golang.org/x/image v0.5.0 // indirect golang.org/x/image v0.5.0 // indirect
golang.org/x/term v0.5.0 // indirect golang.org/x/term v0.8.0 // indirect
golang.org/x/text v0.7.0 // indirect golang.org/x/text v0.9.0 // indirect
gopkg.in/warnings.v0 v0.1.2 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect
) )

View File

@ -67,12 +67,12 @@ github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o=
github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4=
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ=
github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gookit/color v1.4.2/go.mod h1:fqRyamkC1W8uxl+lxCQxOT09l/vYfZ+QeiX3rKQHCoQ= github.com/gookit/color v1.4.2/go.mod h1:fqRyamkC1W8uxl+lxCQxOT09l/vYfZ+QeiX3rKQHCoQ=
github.com/gookit/color v1.5.0/go.mod h1:43aQb+Zerm/BWh2GnrgOQm7ffz7tvQXEKV6BFMl7wAo= github.com/gookit/color v1.5.0/go.mod h1:43aQb+Zerm/BWh2GnrgOQm7ffz7tvQXEKV6BFMl7wAo=
github.com/gookit/color v1.5.2 h1:uLnfXcaFjlrDnQDT+NCBcfhrXqYTx/rcCa6xn01Y8yI= github.com/gookit/color v1.5.2 h1:uLnfXcaFjlrDnQDT+NCBcfhrXqYTx/rcCa6xn01Y8yI=
@ -103,21 +103,22 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/labstack/echo/v4 v4.9.0 h1:wPOF1CE6gvt/kmbMR4dGzWvHMPT+sAEUJOwOTtvITVY= github.com/labstack/echo/v4 v4.10.2 h1:n1jAhnq/elIFTHr1EYpiYtyKgx4RW9ccVgkqByZaN2M=
github.com/labstack/echo/v4 v4.9.0/go.mod h1:xkCDAdFCIf8jsFQ5NnbK7oqaF/yU1A1X20Ltm0OvSks= github.com/labstack/echo/v4 v4.10.2/go.mod h1:OEyqf2//K1DFdE57vw2DRgWY0M7s65IVQO2FzvI4J5k=
github.com/labstack/gommon v0.3.1 h1:OomWaJXm7xR6L1HmEtGyQf26TEn7V6X88mktX9kee9o= github.com/labstack/gommon v0.4.0 h1:y7cvthEAEbU0yHOf4axH8ZG2NH8knB9iNSoTO8dyIk8=
github.com/labstack/gommon v0.3.1/go.mod h1:uW6kP17uPlLJsD3ijUYn3/M5bAxtlZhMI6m3MFxTMTM= github.com/labstack/gommon v0.4.0/go.mod h1:uW6kP17uPlLJsD3ijUYn3/M5bAxtlZhMI6m3MFxTMTM=
github.com/leaanthony/clir v1.0.4/go.mod h1:k/RBkdkFl18xkkACMCLt09bhiZnrGORoxmomeMvDpE0= github.com/leaanthony/clir v1.0.4/go.mod h1:k/RBkdkFl18xkkACMCLt09bhiZnrGORoxmomeMvDpE0=
github.com/leaanthony/clir v1.3.0 h1:L9nPDWrmc/qU9UWZZvRaFajWYuO0np9V5p+5gxyYno0= github.com/leaanthony/clir v1.3.0 h1:L9nPDWrmc/qU9UWZZvRaFajWYuO0np9V5p+5gxyYno0=
github.com/leaanthony/clir v1.3.0/go.mod h1:k/RBkdkFl18xkkACMCLt09bhiZnrGORoxmomeMvDpE0= github.com/leaanthony/clir v1.3.0/go.mod h1:k/RBkdkFl18xkkACMCLt09bhiZnrGORoxmomeMvDpE0=
github.com/leaanthony/debme v1.2.1 h1:9Tgwf+kjcrbMQ4WnPcEIUcQuIZYqdWftzZkBr+i/oOc= github.com/leaanthony/debme v1.2.1 h1:9Tgwf+kjcrbMQ4WnPcEIUcQuIZYqdWftzZkBr+i/oOc=
github.com/leaanthony/debme v1.2.1/go.mod h1:3V+sCm5tYAgQymvSOfYQ5Xx2JCr+OXiD9Jkw3otUjiA= github.com/leaanthony/debme v1.2.1/go.mod h1:3V+sCm5tYAgQymvSOfYQ5Xx2JCr+OXiD9Jkw3otUjiA=
github.com/leaanthony/go-ansi-parser v1.0.1 h1:97v6c5kYppVsbScf4r/VZdXyQ21KQIfeQOk2DgKxGG4= github.com/leaanthony/go-ansi-parser v1.6.0 h1:T8TuMhFB6TUMIUm0oRrSbgJudTFw9csT3ZK09w0t4Pg=
github.com/leaanthony/go-ansi-parser v1.0.1/go.mod h1:7arTzgVI47srICYhvgUV4CGd063sGEeoSlych5yeSPM= github.com/leaanthony/go-ansi-parser v1.6.0/go.mod h1:+vva/2y4alzVmmIEpk9QDhA7vLC5zKDTRwfZGOp3IWU=
github.com/leaanthony/gosod v1.0.3 h1:Fnt+/B6NjQOVuCWOKYRREZnjGyvg+mEhd1nkkA04aTQ= github.com/leaanthony/gosod v1.0.3 h1:Fnt+/B6NjQOVuCWOKYRREZnjGyvg+mEhd1nkkA04aTQ=
github.com/leaanthony/gosod v1.0.3/go.mod h1:BJ2J+oHsQIyIQpnLPjnqFGTMnOZXDbvWtRCSG7jGxs4= github.com/leaanthony/gosod v1.0.3/go.mod h1:BJ2J+oHsQIyIQpnLPjnqFGTMnOZXDbvWtRCSG7jGxs4=
github.com/leaanthony/slicer v1.5.0 h1:aHYTN8xbCCLxJmkNKiLB6tgcMARl4eWmH9/F+S/0HtY=
github.com/leaanthony/slicer v1.5.0/go.mod h1:FwrApmf8gOrpzEWM2J/9Lh79tyq8KTX5AzRtwV7m4AY= github.com/leaanthony/slicer v1.5.0/go.mod h1:FwrApmf8gOrpzEWM2J/9Lh79tyq8KTX5AzRtwV7m4AY=
github.com/leaanthony/slicer v1.6.0 h1:1RFP5uiPJvT93TAHi+ipd3NACobkW53yUiBqZheE/Js=
github.com/leaanthony/slicer v1.6.0/go.mod h1:o/Iz29g7LN0GqH3aMjWAe90381nyZlDNquK+mtH2Fj8=
github.com/leaanthony/winicon v1.0.0 h1:ZNt5U5dY71oEoKZ97UVwJRT4e+5xo5o/ieKuHuk8NqQ= github.com/leaanthony/winicon v1.0.0 h1:ZNt5U5dY71oEoKZ97UVwJRT4e+5xo5o/ieKuHuk8NqQ=
github.com/leaanthony/winicon v1.0.0/go.mod h1:en5xhijl92aphrJdmRPlh4NI1L6wq3gEm0LpXAPghjU= github.com/leaanthony/winicon v1.0.0/go.mod h1:en5xhijl92aphrJdmRPlh4NI1L6wq3gEm0LpXAPghjU=
github.com/lithammer/fuzzysearch v1.1.5 h1:Ag7aKU08wp0R9QCfF4GoGST9HbmAIeLP7xwMrOBEp1c= github.com/lithammer/fuzzysearch v1.1.5 h1:Ag7aKU08wp0R9QCfF4GoGST9HbmAIeLP7xwMrOBEp1c=
@ -126,11 +127,14 @@ github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69
github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
github.com/matryer/is v1.4.0 h1:sosSmIWwkYITGrxZ25ULNDeKiMNzFSr4V/eqBQP0PeE= github.com/matryer/is v1.4.0 h1:sosSmIWwkYITGrxZ25ULNDeKiMNzFSr4V/eqBQP0PeE=
github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU= github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU=
github.com/mattn/go-colorable v0.1.11 h1:nQ+aFkoE2TMGc0b68U2OKSexC+eq46+XwZzWXHRmPYs=
github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.13/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.13/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk= github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk=
github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU= github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU=
@ -148,8 +152,8 @@ github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
github.com/pkg/browser v0.0.0-20210706143420-7d21f8c997e2 h1:acNfDZXmm28D2Yg/c3ALnZStzNaZMSagpbr96vY6Zjc= github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU=
github.com/pkg/browser v0.0.0-20210706143420-7d21f8c997e2/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI= github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
@ -165,14 +169,15 @@ github.com/pterm/pterm v0.12.40/go.mod h1:ffwPLwlbXxP+rxT0GsgDTzS3y3rmpAO1NMjUkG
github.com/pterm/pterm v0.12.49 h1:qeNm0wTWawy6WhKoY8ZKq6qTXFr0s2UtUyRW0yVztEg= github.com/pterm/pterm v0.12.49 h1:qeNm0wTWawy6WhKoY8ZKq6qTXFr0s2UtUyRW0yVztEg=
github.com/pterm/pterm v0.12.49/go.mod h1:D4OBoWNqAfXkm5QLTjIgjNiMXPHemLJHnIreGUsWzWg= github.com/pterm/pterm v0.12.49/go.mod h1:D4OBoWNqAfXkm5QLTjIgjNiMXPHemLJHnIreGUsWzWg=
github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis=
github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k= github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k=
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
github.com/sabhiram/go-gitignore v0.0.0-20210923224102-525f6e181f06 h1:OkMGxebDjyw0ULyrTYWeN0UNCCkmCWfjPnIA2W6oviI= github.com/sabhiram/go-gitignore v0.0.0-20210923224102-525f6e181f06 h1:OkMGxebDjyw0ULyrTYWeN0UNCCkmCWfjPnIA2W6oviI=
github.com/sabhiram/go-gitignore v0.0.0-20210923224102-525f6e181f06/go.mod h1:+ePHsJ1keEjQtpvf9HHw0f4ZeJ0TLRsxhunSI2hYJSs= github.com/sabhiram/go-gitignore v0.0.0-20210923224102-525f6e181f06/go.mod h1:+ePHsJ1keEjQtpvf9HHw0f4ZeJ0TLRsxhunSI2hYJSs=
github.com/samber/lo v1.27.1 h1:sTXwkRiIFIQG+G0HeAvOEnGjqWeWtI9cg5/n51KrxPg= github.com/samber/lo v1.38.1 h1:j2XEAqXKb09Am4ebOg31SpvzUTTs6EN3VfgeLUhPdXM=
github.com/samber/lo v1.27.1/go.mod h1:it33p9UtPMS7z72fP4gw/EIfQB2eI8ke7GR2wc6+Rhg= github.com/samber/lo v1.38.1/go.mod h1:+m/ZKRl6ClXCE2Lgf3MsQlWfh4bn1bz6CXEOxnEXnEA=
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ= github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ=
github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
@ -180,16 +185,17 @@ github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMB
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/tc-hib/winres v0.1.5 h1:2dA5yfjdoEA3UyRaOC92HNMt3jap66pLzoW4MjpC/0M= github.com/tc-hib/winres v0.1.5 h1:2dA5yfjdoEA3UyRaOC92HNMt3jap66pLzoW4MjpC/0M=
github.com/tc-hib/winres v0.1.5/go.mod h1:pe6dOR40VOrGz8PkzreVKNvEKnlE8t4yR8A8naL+t7A= github.com/tc-hib/winres v0.1.5/go.mod h1:pe6dOR40VOrGz8PkzreVKNvEKnlE8t4yR8A8naL+t7A=
github.com/thoas/go-funk v0.9.1 h1:O549iLZqPpTUQ10ykd26sZhzD+rmR5pWhuElrhbC20M=
github.com/tidwall/gjson v1.8.0/go.mod h1:5/xDoumyyDNerp2U36lyolv46b3uF/9Bu6OfyQ9GImk= github.com/tidwall/gjson v1.8.0/go.mod h1:5/xDoumyyDNerp2U36lyolv46b3uF/9Bu6OfyQ9GImk=
github.com/tidwall/gjson v1.9.3 h1:hqzS9wAHMO+KVBBkLxYdkEeeFHuqr95GfClRLKlgK0E= github.com/tidwall/gjson v1.9.3 h1:hqzS9wAHMO+KVBBkLxYdkEeeFHuqr95GfClRLKlgK0E=
github.com/tidwall/gjson v1.9.3/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/gjson v1.9.3/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
@ -201,12 +207,15 @@ github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
github.com/tidwall/sjson v1.1.7 h1:sgVPwu/yygHJ2m1pJDLgGM/h+1F5odx5Q9ljG3imRm8= github.com/tidwall/sjson v1.1.7 h1:sgVPwu/yygHJ2m1pJDLgGM/h+1F5odx5Q9ljG3imRm8=
github.com/tidwall/sjson v1.1.7/go.mod h1:w/yG+ezBeTdUxiKs5NcPicO9diP38nk96QBAbIIGeFs= github.com/tidwall/sjson v1.1.7/go.mod h1:w/yG+ezBeTdUxiKs5NcPicO9diP38nk96QBAbIIGeFs=
github.com/tkrajina/go-reflector v0.5.5 h1:gwoQFNye30Kk7NrExj8zm3zFtrGPqOkzFMLuQZg1DtQ= github.com/tkrajina/go-reflector v0.5.6 h1:hKQ0gyocG7vgMD2M3dRlYN6WBBOmdoOzJ6njQSepKdE=
github.com/tkrajina/go-reflector v0.5.5/go.mod h1:ECbqLgccecY5kPmPmXg1MrHW585yMcDkVl6IvJe64T4= github.com/tkrajina/go-reflector v0.5.6/go.mod h1:ECbqLgccecY5kPmPmXg1MrHW585yMcDkVl6IvJe64T4=
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasttemplate v1.2.1 h1:TVEnxayobAdVkhQfrfes2IzOB6o+z4roRkPF52WA1u4=
github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo=
github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
github.com/wailsapp/go-webview2 v1.0.1 h1:dEJIeEApW/MhO2tTMISZBFZPuW7kwrFA1NtgFB1z1II=
github.com/wailsapp/go-webview2 v1.0.1/go.mod h1:Uk2BePfCRzttBBjFrBmqKGJd41P6QIHeV9kTgIeOZNo=
github.com/wailsapp/mimetype v1.4.1 h1:pQN9ycO7uo4vsUUuPeHEYoUkLVkaRntMnHJxVwYhwHs= github.com/wailsapp/mimetype v1.4.1 h1:pQN9ycO7uo4vsUUuPeHEYoUkLVkaRntMnHJxVwYhwHs=
github.com/wailsapp/mimetype v1.4.1/go.mod h1:9aV5k31bBOv5z6u+QP8TltzvNGJPmNJD4XlAL3U+j3o= github.com/wailsapp/mimetype v1.4.1/go.mod h1:9aV5k31bBOv5z6u+QP8TltzvNGJPmNJD4XlAL3U+j3o=
github.com/wzshiming/ctc v1.2.3 h1:q+hW3IQNsjIlOFBTGZZZeIXTElFM4grF4spW/errh/c= github.com/wzshiming/ctc v1.2.3 h1:q+hW3IQNsjIlOFBTGZZZeIXTElFM4grF4spW/errh/c=
@ -227,26 +236,28 @@ golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnf
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.1.0 h1:MDRAIl0xIo9Io2xV565hzXHw3zVseKrJKodhohM5CjU= golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g=
golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0=
golang.org/x/exp v0.0.0-20220303212507-bbda1eaf7a17 h1:3MTrJm4PyNL9NBqvYDSj3DHl46qQakyfqfWo4jgfaEM= golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 h1:k/i9J1pBpvlfR+9QsetwPyERsqu1GIbi967PQMq3Ivc=
golang.org/x/exp v0.0.0-20220303212507-bbda1eaf7a17/go.mod h1:lgLbSvA5ygNOMpwM/9anMpWVlVJ7Z+cHWq/eFuinpGE= golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w=
golang.org/x/image v0.0.0-20200430140353-33d19683fad8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/image v0.0.0-20200430140353-33d19683fad8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/image v0.0.0-20201208152932-35266b937fa6/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/image v0.0.0-20201208152932-35266b937fa6/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/image v0.5.0 h1:5JMiNunQeQw++mMOz48/ISeNu3Iweh/JaZU8ZLqHRrI= golang.org/x/image v0.5.0 h1:5JMiNunQeQw++mMOz48/ISeNu3Iweh/JaZU8ZLqHRrI=
golang.org/x/image v0.5.0/go.mod h1:FVC7BI/5Ym8R25iw5OLsgshdUBbT1h5jZTpA+mvAdZ4= golang.org/x/image v0.5.0/go.mod h1:FVC7BI/5Ym8R25iw5OLsgshdUBbT1h5jZTpA+mvAdZ4=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.8.0 h1:LUYupSeNrTNCGzR/hVBk2NHZO4hXcVaW1k4Qx7rjPx8=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210326060303-6b1517762897/go.mod h1:uSPa2vr4CLtc/ILN5odXGNXS6mhrKVzTaCXzk9m6W3k= golang.org/x/net v0.0.0-20210326060303-6b1517762897/go.mod h1:uSPa2vr4CLtc/ILN5odXGNXS6mhrKVzTaCXzk9m6W3k=
golang.org/x/net v0.0.0-20210505024714-0287a6fb4125/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210505024714-0287a6fb4125/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g= golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M=
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@ -271,24 +282,28 @@ golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0 h1:n2a8QNdAb0sZNpU9R1ALUXBbY+w51fCQDN+7EdxNBsY= golang.org/x/term v0.8.0 h1:n5xxQn2i3PC0yLAbjTpNT85q/Kgzcr2gIoX9OrJUols=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

View File

@ -2,6 +2,7 @@ package app
import ( import (
"context" "context"
"github.com/wailsapp/wails/v2/internal/frontend" "github.com/wailsapp/wails/v2/internal/frontend"
"github.com/wailsapp/wails/v2/internal/logger" "github.com/wailsapp/wails/v2/internal/logger"
"github.com/wailsapp/wails/v2/internal/menumanager" "github.com/wailsapp/wails/v2/internal/menumanager"
@ -20,6 +21,9 @@ type App struct {
// Indicates if the app is in debug mode // Indicates if the app is in debug mode
debug bool debug bool
// Indicates if the devtools is enabled
devtools bool
// OnStartup/OnShutdown // OnStartup/OnShutdown
startupCallback func(ctx context.Context) startupCallback func(ctx context.Context)
shutdownCallback func(ctx context.Context) shutdownCallback func(ctx context.Context)

View File

@ -42,7 +42,9 @@ func (a *App) Run() error {
func CreateApp(appoptions *options.App) (*App, error) { func CreateApp(appoptions *options.App) (*App, error) {
var err error var err error
ctx := context.WithValue(context.Background(), "debug", true) ctx := context.Background()
ctx = context.WithValue(ctx, "debug", true)
ctx = context.WithValue(ctx, "devtools", true)
// Set up logger // Set up logger
myLogger := logger.New(appoptions.Logger) myLogger := logger.New(appoptions.Logger)
@ -211,7 +213,7 @@ func CreateApp(appoptions *options.App) (*App, error) {
eventHandler := runtime.NewEvents(myLogger) eventHandler := runtime.NewEvents(myLogger)
ctx = context.WithValue(ctx, "events", eventHandler) ctx = context.WithValue(ctx, "events", eventHandler)
messageDispatcher := dispatcher.NewDispatcher(ctx, myLogger, appBindings, eventHandler) messageDispatcher := dispatcher.NewDispatcher(ctx, myLogger, appBindings, eventHandler, appoptions.ErrorFormatter)
// Create the frontends and register to event handler // Create the frontends and register to event handler
desktopFrontend := desktop.NewFrontend(ctx, appoptions, myLogger, appBindings, messageDispatcher) desktopFrontend := desktop.NewFrontend(ctx, appoptions, myLogger, appBindings, messageDispatcher)
@ -228,6 +230,7 @@ func CreateApp(appoptions *options.App) (*App, error) {
startupCallback: appoptions.OnStartup, startupCallback: appoptions.OnStartup,
shutdownCallback: appoptions.OnShutdown, shutdownCallback: appoptions.OnShutdown,
debug: true, debug: true,
devtools: true,
} }
result.options = appoptions result.options = appoptions

View File

@ -0,0 +1,7 @@
//go:build devtools
package app
func IsDevtoolsEnabled() bool {
return true
}

View File

@ -0,0 +1,7 @@
//go:build !devtools
package app
func IsDevtoolsEnabled() bool {
return false
}

View File

@ -34,7 +34,9 @@ func CreateApp(appoptions *options.App) (*App, error) {
options.MergeDefaults(appoptions) options.MergeDefaults(appoptions)
debug := IsDebug() debug := IsDebug()
devtools := IsDevtoolsEnabled()
ctx = context.WithValue(ctx, "debug", debug) ctx = context.WithValue(ctx, "debug", debug)
ctx = context.WithValue(ctx, "devtools", devtools)
// Set up logger // Set up logger
myLogger := logger.New(appoptions.Logger) myLogger := logger.New(appoptions.Logger)
@ -80,7 +82,7 @@ func CreateApp(appoptions *options.App) (*App, error) {
ctx = context.WithValue(ctx, "buildtype", "production") ctx = context.WithValue(ctx, "buildtype", "production")
} }
messageDispatcher := dispatcher.NewDispatcher(ctx, myLogger, appBindings, eventHandler) messageDispatcher := dispatcher.NewDispatcher(ctx, myLogger, appBindings, eventHandler, appoptions.ErrorFormatter)
appFrontend := desktop.NewFrontend(ctx, appoptions, myLogger, appBindings, messageDispatcher) appFrontend := desktop.NewFrontend(ctx, appoptions, myLogger, appBindings, messageDispatcher)
eventHandler.AddFrontend(appFrontend) eventHandler.AddFrontend(appFrontend)
@ -93,6 +95,7 @@ func CreateApp(appoptions *options.App) (*App, error) {
startupCallback: appoptions.OnStartup, startupCallback: appoptions.OnStartup,
shutdownCallback: appoptions.OnShutdown, shutdownCallback: appoptions.OnShutdown,
debug: debug, debug: debug,
devtools: devtools,
options: appoptions, options: appoptions,
} }

View File

@ -17,7 +17,7 @@
#define WindowStartsMinimised 2 #define WindowStartsMinimised 2
#define WindowStartsFullscreen 3 #define WindowStartsFullscreen 3
WailsContext* Create(const char* title, int width, int height, int frameless, int resizable, int fullscreen, int fullSizeContent, int hideTitleBar, int titlebarAppearsTransparent, int hideTitle, int useToolbar, int hideToolbarSeparator, int webviewIsTransparent, int alwaysOnTop, int hideWindowOnClose, const char *appearance, int windowIsTranslucent, int debug, int windowStartState, int startsHidden, int minWidth, int minHeight, int maxWidth, int maxHeight, bool fraudulentWebsiteWarningEnabled); WailsContext* Create(const char* title, int width, int height, int frameless, int resizable, int fullscreen, int fullSizeContent, int hideTitleBar, int titlebarAppearsTransparent, int hideTitle, int useToolbar, int hideToolbarSeparator, int webviewIsTransparent, int alwaysOnTop, int hideWindowOnClose, const char *appearance, int windowIsTranslucent, int devtools, int defaultContextMenu, int windowStartState, int startsHidden, int minWidth, int minHeight, int maxWidth, int maxHeight, bool fraudulentWebsiteWarningEnabled);
void Run(void*, const char* url); void Run(void*, const char* url);
void SetTitle(void* ctx, const char *title); void SetTitle(void* ctx, const char *title);

View File

@ -13,13 +13,14 @@
#import "WailsMenu.h" #import "WailsMenu.h"
#import "WailsMenuItem.h" #import "WailsMenuItem.h"
WailsContext* Create(const char* title, int width, int height, int frameless, int resizable, int fullscreen, int fullSizeContent, int hideTitleBar, int titlebarAppearsTransparent, int hideTitle, int useToolbar, int hideToolbarSeparator, int webviewIsTransparent, int alwaysOnTop, int hideWindowOnClose, const char *appearance, int windowIsTranslucent, int debug, int windowStartState, int startsHidden, int minWidth, int minHeight, int maxWidth, int maxHeight, bool fraudulentWebsiteWarningEnabled) { WailsContext* Create(const char* title, int width, int height, int frameless, int resizable, int fullscreen, int fullSizeContent, int hideTitleBar, int titlebarAppearsTransparent, int hideTitle, int useToolbar, int hideToolbarSeparator, int webviewIsTransparent, int alwaysOnTop, int hideWindowOnClose, const char *appearance, int windowIsTranslucent, int devtools, int defaultContextMenu, int windowStartState, int startsHidden, int minWidth, int minHeight, int maxWidth, int maxHeight, bool fraudulentWebsiteWarningEnabled) {
[NSApplication sharedApplication]; [NSApplication sharedApplication];
WailsContext *result = [WailsContext new]; WailsContext *result = [WailsContext new];
result.debug = debug; result.devtools = devtools;
result.defaultContextMenu = defaultContextMenu;
if ( windowStartState == WindowStartsFullscreen ) { if ( windowStartState == WindowStartsFullscreen ) {
fullscreen = 1; fullscreen = 1;

View File

@ -44,7 +44,8 @@
@property bool alwaysOnTop; @property bool alwaysOnTop;
@property bool debug; @property bool devtools;
@property bool defaultContextMenu;
@property (retain) WKUserContentController* userContentController; @property (retain) WKUserContentController* userContentController;

View File

@ -225,12 +225,12 @@ typedef void (^schemeTaskCaller)(id<WKURLSchemeTask>);
[userContentController addScriptMessageHandler:self name:@"external"]; [userContentController addScriptMessageHandler:self name:@"external"];
config.userContentController = userContentController; config.userContentController = userContentController;
self.userContentController = userContentController; self.userContentController = userContentController;
if (self.debug) { if (self.devtools) {
[config.preferences setValue:@YES forKey:@"developerExtrasEnabled"]; [config.preferences setValue:@YES forKey:@"developerExtrasEnabled"];
} else { } else if (!self.defaultContextMenu) {
// Disable default context menus // Disable default context menus
WKUserScript *initScript = [WKUserScript new]; WKUserScript *initScript = [WKUserScript new];
[initScript initWithSource:@"window.wails.flags.disableWailsDefaultContextMenu = true;" [initScript initWithSource:@"window.wails.flags.disableDefaultContextMenu = true;"
injectionTime:WKUserScriptInjectionTimeAtDocumentEnd injectionTime:WKUserScriptInjectionTimeAtDocumentEnd
forMainFrameOnly:false]; forMainFrameOnly:false];
[userContentController addUserScript:initScript]; [userContentController addUserScript:initScript];

View File

@ -47,6 +47,7 @@ type Frontend struct {
frontendOptions *options.App frontendOptions *options.App
logger *logger.Logger logger *logger.Logger
debug bool debug bool
devtools bool
// Assets // Assets
assets *assetserver.AssetServer assets *assetserver.AssetServer
@ -151,12 +152,18 @@ func (f *Frontend) WindowSetDarkTheme() {
func (f *Frontend) Run(ctx context.Context) error { func (f *Frontend) Run(ctx context.Context) error {
f.ctx = ctx f.ctx = ctx
var _debug = ctx.Value("debug") var _debug = ctx.Value("debug")
var _devtools = ctx.Value("devtools")
if _debug != nil { if _debug != nil {
f.debug = _debug.(bool) f.debug = _debug.(bool)
} }
if _devtools != nil {
f.devtools = _devtools.(bool)
}
mainWindow := NewWindow(f.frontendOptions, f.debug) mainWindow := NewWindow(f.frontendOptions, f.debug, f.devtools)
f.mainWindow = mainWindow f.mainWindow = mainWindow
f.mainWindow.Center() f.mainWindow.Center()

View File

@ -215,10 +215,11 @@ int main(int argc, const char * argv[]) {
int hideWindowOnClose = 0; int hideWindowOnClose = 0;
const char* appearance = "NSAppearanceNameDarkAqua"; const char* appearance = "NSAppearanceNameDarkAqua";
int windowIsTranslucent = 1; int windowIsTranslucent = 1;
int debug = 1; int devtools = 1;
int defaultContextMenu = 1;
int windowStartState = 0; int windowStartState = 0;
int startsHidden = 0; int startsHidden = 0;
WailsContext *result = Create("OI OI!",400,400, frameless, resizable, fullscreen, fullSizeContent, hideTitleBar, titlebarAppearsTransparent, hideTitle, useToolbar, hideToolbarSeparator, webviewIsTransparent, alwaysOnTop, hideWindowOnClose, appearance, windowIsTranslucent, debug, windowStartState, WailsContext *result = Create("OI OI!",400,400, frameless, resizable, fullscreen, fullSizeContent, hideTitleBar, titlebarAppearsTransparent, hideTitle, useToolbar, hideToolbarSeparator, webviewIsTransparent, alwaysOnTop, hideWindowOnClose, appearance, windowIsTranslucent, devtools, defaultContextMenu, windowStartState,
startsHidden, 400, 400, 600, 600, false); startsHidden, 400, 400, 600, 600, false);
SetBackgroundColour(result, 255, 0, 0, 255); SetBackgroundColour(result, 255, 0, 0, 255);
void *m = NewMenu(""); void *m = NewMenu("");

View File

@ -40,7 +40,7 @@ func bool2Cint(value bool) C.int {
return C.int(0) return C.int(0)
} }
func NewWindow(frontendOptions *options.App, debugMode bool) *Window { func NewWindow(frontendOptions *options.App, debug bool, devtools bool) *Window {
c := NewCalloc() c := NewCalloc()
defer c.Free() defer c.Free()
@ -51,7 +51,8 @@ func NewWindow(frontendOptions *options.App, debugMode bool) *Window {
alwaysOnTop := bool2Cint(frontendOptions.AlwaysOnTop) alwaysOnTop := bool2Cint(frontendOptions.AlwaysOnTop)
hideWindowOnClose := bool2Cint(frontendOptions.HideWindowOnClose) hideWindowOnClose := bool2Cint(frontendOptions.HideWindowOnClose)
startsHidden := bool2Cint(frontendOptions.StartHidden) startsHidden := bool2Cint(frontendOptions.StartHidden)
debug := bool2Cint(debugMode) devtoolsEnabled := bool2Cint(devtools)
defaultContextMenu := bool2Cint(frontendOptions.EnableDefaultContextMenu)
var fullSizeContent, hideTitleBar, hideTitle, useToolbar, webviewIsTransparent C.int var fullSizeContent, hideTitleBar, hideTitle, useToolbar, webviewIsTransparent C.int
var titlebarAppearsTransparent, hideToolbarSeparator, windowIsTranslucent C.int var titlebarAppearsTransparent, hideToolbarSeparator, windowIsTranslucent C.int
@ -86,8 +87,8 @@ func NewWindow(frontendOptions *options.App, debugMode bool) *Window {
} }
var context *C.WailsContext = C.Create(title, width, height, frameless, resizable, fullscreen, fullSizeContent, var context *C.WailsContext = C.Create(title, width, height, frameless, resizable, fullscreen, fullSizeContent,
hideTitleBar, titlebarAppearsTransparent, hideTitle, useToolbar, hideToolbarSeparator, webviewIsTransparent, hideTitleBar, titlebarAppearsTransparent, hideTitle, useToolbar, hideToolbarSeparator, webviewIsTransparent,
alwaysOnTop, hideWindowOnClose, appearance, windowIsTranslucent, debug, windowStartState, startsHidden, alwaysOnTop, hideWindowOnClose, appearance, windowIsTranslucent, devtoolsEnabled, defaultContextMenu,
minWidth, minHeight, maxWidth, maxHeight, enableFraudulentWebsiteWarnings) windowStartState, startsHidden, minWidth, minHeight, maxWidth, maxHeight, enableFraudulentWebsiteWarnings)
// Create menu // Create menu
result := &Window{ result := &Window{
@ -114,7 +115,7 @@ func NewWindow(frontendOptions *options.App, debugMode bool) *Window {
result.SetApplicationMenu(frontendOptions.Menu) result.SetApplicationMenu(frontendOptions.Menu)
} }
if debugMode && frontendOptions.Debug.OpenInspectorOnStartup { if debug && frontendOptions.Debug.OpenInspectorOnStartup {
showInspector(result.context) showInspector(result.context)
} }
return result return result

View File

@ -106,6 +106,7 @@ type Frontend struct {
frontendOptions *options.App frontendOptions *options.App
logger *logger.Logger logger *logger.Logger
debug bool debug bool
devtools bool
// Assets // Assets
assets *assetserver.AssetServer assets *assetserver.AssetServer
@ -176,13 +177,25 @@ func NewFrontend(ctx context.Context, appoptions *options.App, myLogger *logger.
go result.startMessageProcessor() go result.startMessageProcessor()
var _debug = ctx.Value("debug") var _debug = ctx.Value("debug")
var _devtools = ctx.Value("devtools")
if _debug != nil { if _debug != nil {
result.debug = _debug.(bool) result.debug = _debug.(bool)
} }
result.mainWindow = NewWindow(appoptions, result.debug) if _devtools != nil {
result.devtools = _devtools.(bool)
}
result.mainWindow = NewWindow(appoptions, result.debug, result.devtools)
C.install_signal_handlers() C.install_signal_handlers()
if appoptions.Linux != nil && appoptions.Linux.ProgramName != "" {
prgname := C.CString(appoptions.Linux.ProgramName)
C.g_set_prgname(prgname)
C.free(unsafe.Pointer(prgname))
}
return result return result
} }

View File

@ -37,6 +37,7 @@ func gtkBool(input bool) C.gboolean {
type Window struct { type Window struct {
appoptions *options.App appoptions *options.App
debug bool debug bool
devtools bool
gtkWindow unsafe.Pointer gtkWindow unsafe.Pointer
contentManager unsafe.Pointer contentManager unsafe.Pointer
webview unsafe.Pointer webview unsafe.Pointer
@ -54,12 +55,13 @@ func bool2Cint(value bool) C.int {
return C.int(0) return C.int(0)
} }
func NewWindow(appoptions *options.App, debug bool) *Window { func NewWindow(appoptions *options.App, debug bool, devtools bool) *Window {
validateWebKit2Version(appoptions) validateWebKit2Version(appoptions)
result := &Window{ result := &Window{
appoptions: appoptions, appoptions: appoptions,
debug: debug, debug: debug,
devtools: devtools,
minHeight: appoptions.MinHeight, minHeight: appoptions.MinHeight,
minWidth: appoptions.MinWidth, minWidth: appoptions.MinWidth,
maxHeight: appoptions.MaxHeight, maxHeight: appoptions.MaxHeight,
@ -95,9 +97,9 @@ func NewWindow(appoptions *options.App, debug bool) *Window {
defer C.free(unsafe.Pointer(buttonPressedName)) defer C.free(unsafe.Pointer(buttonPressedName))
C.ConnectButtons(unsafe.Pointer(webview)) C.ConnectButtons(unsafe.Pointer(webview))
if debug { if devtools {
C.DevtoolsEnabled(unsafe.Pointer(webview), C.int(1), C.bool(appoptions.Debug.OpenInspectorOnStartup)) C.DevtoolsEnabled(unsafe.Pointer(webview), C.int(1), C.bool(debug && appoptions.Debug.OpenInspectorOnStartup))
} else { } else if !appoptions.EnableDefaultContextMenu {
C.DisableContextMenu(unsafe.Pointer(webview)) C.DisableContextMenu(unsafe.Pointer(webview))
} }

View File

@ -21,9 +21,9 @@ import (
"time" "time"
"github.com/bep/debounce" "github.com/bep/debounce"
"github.com/wailsapp/go-webview2/pkg/edge"
"github.com/wailsapp/wails/v2/internal/binding" "github.com/wailsapp/wails/v2/internal/binding"
"github.com/wailsapp/wails/v2/internal/frontend" "github.com/wailsapp/wails/v2/internal/frontend"
"github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge"
"github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/win32" "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/win32"
"github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/winc" "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/winc"
"github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/winc/w32" "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/winc/w32"
@ -48,6 +48,7 @@ type Frontend struct {
logger *logger.Logger logger *logger.Logger
chromium *edge.Chromium chromium *edge.Chromium
debug bool debug bool
devtools bool
// Assets // Assets
assets *assetserver.AssetServer assets *assetserver.AssetServer
@ -142,9 +143,14 @@ func (f *Frontend) Run(ctx context.Context) error {
f.mainWindow = mainWindow f.mainWindow = mainWindow
var _debug = ctx.Value("debug") var _debug = ctx.Value("debug")
var _devtools = ctx.Value("devtools")
if _debug != nil { if _debug != nil {
f.debug = _debug.(bool) f.debug = _debug.(bool)
} }
if _devtools != nil {
f.devtools = _devtools.(bool)
}
f.WindowCenter() f.WindowCenter()
f.setupChromium() f.setupChromium()
@ -489,11 +495,11 @@ func (f *Frontend) setupChromium() {
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
err = settings.PutAreDefaultContextMenusEnabled(f.debug) err = settings.PutAreDefaultContextMenusEnabled(f.devtools || f.frontendOptions.EnableDefaultContextMenu)
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
err = settings.PutAreDevToolsEnabled(f.debug) err = settings.PutAreDevToolsEnabled(f.devtools)
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }

View File

@ -1,22 +0,0 @@
MIT License
Copyright (c) 2020 John Chadwick
Some portions Copyright (c) 2017 Serge Zaitsev
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -1,27 +0,0 @@
# go-webview2
This is a proof of concept for embedding Webview2 into Go without CGo. It is based
on [webview/webview](https://github.com/webview/webview) and provides a compatible API.
## Notice
Because this version doesn't currently have an EdgeHTML fallback, it will not work unless you have a Webview2 runtime
installed. In addition, it requires the Webview2Loader DLL in order to function. Adding an EdgeHTML fallback should be
technically possible but will likely require much worse hacks since the API is not strictly COM to my knowledge.
## Demo
For now, you'll need to install the Webview2 runtime, as it does not ship with Windows.
[WebView2 runtime](https://developer.microsoft.com/en-us/microsoft-edge/webview2/)
After that, you should be able to run go-webview2 directly:
```
go run go-webview2/cmd/demo
```
This will use go-winloader to load an embedded copy of WebView2Loader.dll.
If this does not work, please try running from a directory that has an appropriate copy of `WebView2Loader.dll` for your
GOARCH. If _that_ worked, *please* file a bug so we can figure out what's wrong with go-winloader :)

View File

@ -1,157 +0,0 @@
//go:build windows
package w32
import (
"syscall"
"unicode/utf16"
"unsafe"
"golang.org/x/sys/windows"
)
var (
ole32 = windows.NewLazySystemDLL("ole32")
Ole32CoInitializeEx = ole32.NewProc("CoInitializeEx")
kernel32 = windows.NewLazySystemDLL("kernel32")
Kernel32GetCurrentThreadID = kernel32.NewProc("GetCurrentThreadId")
shlwapi = windows.NewLazySystemDLL("shlwapi")
shlwapiSHCreateMemStream = shlwapi.NewProc("SHCreateMemStream")
user32 = windows.NewLazySystemDLL("user32")
User32LoadImageW = user32.NewProc("LoadImageW")
User32GetSystemMetrics = user32.NewProc("GetSystemMetrics")
User32RegisterClassExW = user32.NewProc("RegisterClassExW")
User32CreateWindowExW = user32.NewProc("CreateWindowExW")
User32DestroyWindow = user32.NewProc("DestroyWindow")
User32ShowWindow = user32.NewProc("ShowWindow")
User32UpdateWindow = user32.NewProc("UpdateWindow")
User32SetFocus = user32.NewProc("SetFocus")
User32GetMessageW = user32.NewProc("GetMessageW")
User32TranslateMessage = user32.NewProc("TranslateMessage")
User32DispatchMessageW = user32.NewProc("DispatchMessageW")
User32DefWindowProcW = user32.NewProc("DefWindowProcW")
User32GetClientRect = user32.NewProc("GetClientRect")
User32PostQuitMessage = user32.NewProc("PostQuitMessage")
User32SetWindowTextW = user32.NewProc("SetWindowTextW")
User32PostThreadMessageW = user32.NewProc("PostThreadMessageW")
User32GetWindowLongPtrW = user32.NewProc("GetWindowLongPtrW")
User32SetWindowLongPtrW = user32.NewProc("SetWindowLongPtrW")
User32AdjustWindowRect = user32.NewProc("AdjustWindowRect")
User32SetWindowPos = user32.NewProc("SetWindowPos")
)
const (
SystemMetricsCxIcon = 11
SystemMetricsCyIcon = 12
)
const (
SWShow = 5
)
const (
SWPNoZOrder = 0x0004
SWPNoActivate = 0x0010
SWPNoMove = 0x0002
SWPFrameChanged = 0x0020
)
const (
WMDestroy = 0x0002
WMMove = 0x0003
WMSize = 0x0005
WMClose = 0x0010
WMQuit = 0x0012
WMGetMinMaxInfo = 0x0024
WMNCLButtonDown = 0x00A1
WMMoving = 0x0216
WMApp = 0x8000
)
const (
GWLStyle = -16
)
const (
WSOverlapped = 0x00000000
WSMaximizeBox = 0x00020000
WSThickFrame = 0x00040000
WSCaption = 0x00C00000
WSSysMenu = 0x00080000
WSMinimizeBox = 0x00020000
WSOverlappedWindow = (WSOverlapped | WSCaption | WSSysMenu | WSThickFrame | WSMinimizeBox | WSMaximizeBox)
)
type WndClassExW struct {
CbSize uint32
Style uint32
LpfnWndProc uintptr
CnClsExtra int32
CbWndExtra int32
HInstance windows.Handle
HIcon windows.Handle
HCursor windows.Handle
HbrBackground windows.Handle
LpszMenuName *uint16
LpszClassName *uint16
HIconSm windows.Handle
}
type Rect struct {
Left int32
Top int32
Right int32
Bottom int32
}
type MinMaxInfo struct {
PtReserved Point
PtMaxSize Point
PtMaxPosition Point
PtMinTrackSize Point
PtMaxTrackSize Point
}
type Point struct {
X, Y int32
}
type Msg struct {
Hwnd syscall.Handle
Message uint32
WParam uintptr
LParam uintptr
Time uint32
Pt Point
LPrivate uint32
}
func Utf16PtrToString(p *uint16) string {
if p == nil {
return ""
}
// Find NUL terminator.
end := unsafe.Pointer(p)
n := 0
for *(*uint16)(end) != 0 {
end = unsafe.Pointer(uintptr(end) + unsafe.Sizeof(*p))
n++
}
s := (*[(1 << 30) - 1]uint16)(unsafe.Pointer(p))[:n:n]
return string(utf16.Decode(s))
}
func SHCreateMemStream(data []byte) (uintptr, error) {
ret, _, err := shlwapiSHCreateMemStream.Call(
uintptr(unsafe.Pointer(&data[0])),
uintptr(len(data)),
)
if ret == 0 {
return 0, err
}
return ret, nil
}

View File

@ -1,239 +0,0 @@
//go:build windows
package combridge
import (
"fmt"
"runtime"
"sync"
"sync/atomic"
)
var (
comIfcePointersL sync.RWMutex
comIfcePointers = map[uintptr]*comObject{} // Map from ComInterfacePointer to the Go ComObject
)
// Resolve the GoInterface of the specified ComInterfacePointer
func Resolve[T IUnknown](ifceP uintptr) T {
comIfcePointersL.RLock()
comObj := comIfcePointers[ifceP]
comIfcePointersL.RUnlock()
var n T
if comObj != nil {
t := comObj.resolve(ifceP)
if t != nil {
n = t.(T)
}
}
return n
}
// New returns a new ComObject which implements the specified Com Interface, com calls will be redirected
// to the specified go interface.
func New[T IUnknown](obj T) *ComObject[T] {
cObj := new(
ifceDef[T]{obj},
)
return newComObject[T](cObj)
}
// New2 returns a new ComObject which implements the two specified Com Interfaces, com calls will be redirected
// to those interfaces accordingly.
// This is needed if a ComObject should implement two interfaces that are not descendants of each other,
// then you get multiple inheritance.
func New2[T IUnknown, T2 IUnknown](obj T, obj2 T2) *ComObject[T] {
cObj := new(
ifceDef[T]{obj},
ifceDef[T2]{obj2},
)
return newComObject[T](cObj)
}
// new returns a new ComObject which implements multiple specified Com Interfaces, com calls will be redirected
// to the specified go interfaces accordingly.
// This is needed if a ComObject should implement multiple interfaces that are not descendants of each other,
// then you get multiple inheritance.
func new(impls ...ifceImpl) *comObject {
impls = append([]ifceImpl{ifceDef[IUnknown]{}}, impls...)
cObj := &comObject{
refCount: 1,
ifces: map[string]int{},
ifcesImpl: make([]comInterfaceDesc, len(impls)),
}
for i, ifceDef := range impls {
vtable, err := ifceDef.ifce()
if err != nil {
panic(err)
}
needsImplement := false
for table := vtable; table != nil; table = table.Parent {
guid := table.ComGUID
if i, found := cObj.ifces[guid]; found {
// This Interface is already implemented
if guid == iUnknownGUID {
// IUnknown is a special interface and never has an user specific implementation
} else if cObj.ifcesImpl[i].impl != ifceDef.impl() {
panic(fmt.Sprintf("Interface '%s' is already implemented by another object", table.Name))
}
break
}
needsImplement = true
cObj.ifces[guid] = i
}
if !needsImplement {
continue
}
ifceP, ifcePSlice := allocUintptrObject(1)
ifcePSlice[0] = vtable.ComVTable
cObj.ifcesImpl[i] = comInterfaceDesc{ifceP, ifceDef.impl()}
}
comIfcePointersL.Lock()
for _, ifceImpl := range cObj.ifcesImpl {
comIfcePointers[ifceImpl.ref] = cObj
}
comIfcePointersL.Unlock()
return cObj
}
func newComObject[T IUnknown](comObj *comObject) *ComObject[T] {
c := &ComObject[T]{obj: comObj}
// Make sure to async release since release needs locks and might block the finalizer goroutine for a longer period
runtime.SetFinalizer(c, func(obj *ComObject[T]) { obj.close(true) })
return c
}
// ComObject describes an exported go instance to be used as a ComObject which implements
// the specified Interface.
type ComObject[T IUnknown] struct {
obj *comObject
closed int32
}
// Ref returns the native uintptr that points to the ComObject that is an interface pointer to T.
// This can be used in native calls. If the object has been closed this function will panic.
func (o *ComObject[T]) Ref() uintptr {
if atomic.LoadInt32(&o.closed) != 0 {
panic("ComObject has been released")
}
return o.obj.queryInterface(guidOf[T](), false)
}
// Close releases the native com object from the go side. It will only be destroyed if the ref counter
// reaches zero.
// After closing `Ref()` will panic.
func (o *ComObject[T]) Close() error {
o.close(false)
return nil
}
// close releases the native com object from the go side. It will only be destroyed if the ref counter
// reaches zero.
// After closing `Ref()` will panic.
func (o *ComObject[T]) close(asyncRelease bool) {
if atomic.CompareAndSwapInt32(&o.closed, 0, 1) {
runtime.SetFinalizer(o, nil)
if asyncRelease {
go o.obj.release()
} else {
o.obj.release()
}
}
}
type comInterfaceDesc struct {
ref uintptr // The native Com InterfacePointer
impl any // The golang target object
}
type comObject struct {
l sync.Mutex
refCount int32
ifces map[string]int // Map of ComInterfaceGUID to Interface Slots
ifcesImpl []comInterfaceDesc // Slots with InterfaceDescriptors
}
func (c *comObject) queryInterface(ifceGUID string, withAddRef bool) uintptr {
c.l.Lock()
defer c.l.Unlock()
if c.refCount <= 0 {
panic("call on released com object")
}
i, found := c.ifces[ifceGUID]
if !found {
return 0
}
if withAddRef {
c.refCount++
}
return c.ifcesImpl[i].ref
}
func (c *comObject) resolve(ifceP uintptr) any {
c.l.Lock()
defer c.l.Unlock()
if c.refCount <= 0 {
panic("call on destroyed com object")
}
for _, ifce := range c.ifcesImpl {
if ifce.ref != ifceP {
continue
}
return ifce.impl
}
return nil
}
func (c *comObject) addRef() int32 {
c.l.Lock()
defer c.l.Unlock()
if c.refCount <= 0 {
panic("call on destroyed com object")
}
c.refCount++
return c.refCount
}
func (c *comObject) release() int32 {
c.l.Lock()
defer c.l.Unlock()
if c.refCount <= 0 {
panic("call on destroyed com object")
}
if c.refCount--; c.refCount == 0 {
comIfcePointersL.Lock()
for _, ref := range c.ifcesImpl {
delete(comIfcePointers, ref.ref)
}
comIfcePointersL.Unlock()
for _, impl := range c.ifcesImpl {
ref := impl.ref
if ref == 0 {
continue
}
globalFree(ref)
}
}
return c.refCount
}

View File

@ -1,56 +0,0 @@
//go:build windows
package combridge
import (
"golang.org/x/sys/windows"
)
const iUnknownGUID = "{00000000-0000-0000-C000-000000000046}"
func init() {
registerVTableInternal[IUnknown, IUnknown](
iUnknownGUID,
true,
iUnknownQueryInterface,
iUnknownAddRef,
iUnknownRelease,
)
}
type IUnknown interface{}
func iUnknownQueryInterface(this uintptr, refiid *windows.GUID, ppvObject *uintptr) uintptr {
if refiid == nil || ppvObject == nil {
return uintptr(windows.E_INVALIDARG)
}
comIfcePointersL.RLock()
obj := comIfcePointers[this]
comIfcePointersL.RUnlock()
ref := obj.queryInterface(refiid.String(), true)
if ref != 0 {
*ppvObject = ref
return windows.NO_ERROR
}
*ppvObject = 0
return uintptr(windows.E_NOINTERFACE)
}
func iUnknownAddRef(this uintptr) uintptr {
comIfcePointersL.RLock()
obj := comIfcePointers[this]
comIfcePointersL.RUnlock()
return uintptr(obj.addRef())
}
func iUnknownRelease(this uintptr) uintptr {
comIfcePointersL.RLock()
obj := comIfcePointers[this]
comIfcePointersL.RUnlock()
return uintptr(obj.release())
}

View File

@ -1,74 +0,0 @@
//go:build windows
package combridge
import (
"syscall"
"unsafe"
"golang.org/x/sys/windows"
)
// IUnknownFromPointer cast a generic pointer into a IUnknownImpl pointer
func IUnknownFromPointer(ref unsafe.Pointer) *IUnknownImpl {
return (*IUnknownImpl)(ref)
}
// IUnknownFromPointer cast native pointer into a IUnknownImpl pointer
func IUnknownFromUintptr(ref uintptr) *IUnknownImpl {
return IUnknownFromPointer(unsafe.Pointer(ref))
}
type IUnknownVtbl struct {
queryInterface uintptr
addRef uintptr
release uintptr
}
func (i *IUnknownVtbl) QueryInterface(this unsafe.Pointer, refiid *windows.GUID, ppvObject **IUnknownImpl) error {
r, _, _ := syscall.SyscallN(
i.queryInterface,
uintptr(this),
uintptr(unsafe.Pointer(refiid)),
uintptr(unsafe.Pointer(ppvObject)),
)
if r != uintptr(windows.S_OK) {
return syscall.Errno(r)
}
return nil
}
func (i *IUnknownVtbl) AddRef(this unsafe.Pointer) uint32 {
r, _, _ := syscall.SyscallN(
i.addRef,
uintptr(this),
)
return uint32(r)
}
func (i *IUnknownVtbl) Release(this unsafe.Pointer) uint32 {
r, _, _ := syscall.SyscallN(
i.release,
uintptr(this),
)
return uint32(r)
}
type IUnknownImpl struct {
vtbl *IUnknownVtbl
}
func (i *IUnknownImpl) QueryInterface(refiid *windows.GUID, ppvObject **IUnknownImpl) error {
return i.vtbl.QueryInterface(unsafe.Pointer(i), refiid, ppvObject)
}
func (i *IUnknownImpl) AddRef() uint32 {
return i.vtbl.AddRef(unsafe.Pointer(i))
}
func (i *IUnknownImpl) Release() uint32 {
return i.vtbl.Release(unsafe.Pointer(i))
}

View File

@ -1,39 +0,0 @@
//go:build windows
package combridge
import (
"unsafe"
"golang.org/x/sys/windows"
)
var (
modkernel32 = windows.NewLazySystemDLL("kernel32.dll")
procGlobalAlloc = modkernel32.NewProc("GlobalAlloc")
procGlobalFree = modkernel32.NewProc("GlobalFree")
uintptrSize = unsafe.Sizeof(uintptr(0))
)
func allocUintptrObject(size int) (uintptr, []uintptr) {
v := globalAlloc(uintptr(size) * uintptrSize)
slice := unsafe.Slice((*uintptr)(unsafe.Pointer(v)), size)
return v, slice
}
func globalAlloc(dwBytes uintptr) uintptr {
ret, _, _ := procGlobalAlloc.Call(uintptr(0), dwBytes)
if ret == 0 {
panic("globalAlloc failed")
}
return ret
}
func globalFree(data uintptr) {
ret, _, _ := procGlobalFree.Call(data)
if ret != 0 {
panic("globalFree failed")
}
}

View File

@ -1,147 +0,0 @@
//go:build windows
package combridge
import (
"fmt"
"reflect"
"sync"
"golang.org/x/sys/windows"
)
var (
vTablesL sync.Mutex
vTables = make(map[string]*vTable)
)
// RegisterVTable registers the vtable trampoline methods for the specified ComInterface
// TBase is the base interface of T, and must be another ComInterface which roots in IUnknown or IUnknown itself.
// The first paramter of the fn is always the uintptr of the ComObject and the GoObject can be resolved with Resolve().
// After having resolved the GoObject the call must be redirected to the GoObject.
// Typically a trampoline FN looks like this.
//
// func _ICoreWebView2NavigationCompletedEventHandlerInvoke(this uintptr, sender *ICoreWebView2, args *ICoreWebView2NavigationCompletedEventArgs) uintptr {
// return combridge.Resolve[_ICoreWebView2NavigationCompletedEventHandler](this).NavigationCompleted(sender, args)
// }
//
// The order of registration must be in the correct order as specified in the IDL of the interface.
func RegisterVTable[TParent, T IUnknown](guid string, fns ...interface{}) {
registerVTableInternal[TParent, T](guid, false, fns...)
}
type vTable struct {
Parent *vTable
Name string
ComGUID string
ComVTable uintptr
ComProcs []uintptr
}
func registerVTableInternal[TParent, T IUnknown](guid string, isInternal bool, fns ...interface{}) {
vTablesL.Lock()
defer vTablesL.Unlock()
t, tName := typeInterfaceToString[T]()
tParent, tParentName := typeInterfaceToString[TParent]()
if !t.Implements(tParent) {
panic(fmt.Errorf("RegisterVTable '%s': '%s' must implement '%s'", tName, tName, tParentName))
}
if !isInternal {
if t == reflect.TypeOf((*IUnknown)(nil)).Elem() {
panic(fmt.Errorf("RegisterVTable '%s' IUnknown can't be registered", tName))
}
if t == tParent {
panic(fmt.Errorf("RegisterVTable '%s': T and TParent can't be the same type", tName))
}
}
var parent *vTable
var parentProcs []uintptr
var parentProcsCount int
if t != tParent {
parent = vTables[tParentName]
if parent == nil {
panic(fmt.Errorf("RegisterVTable '%s': Parent VTable '%s' not registered", tName, tParentName))
}
parentProcs = parent.ComProcs
parentProcsCount = len(parentProcs)
}
comGuid, err := windows.GUIDFromString(guid)
if err != nil {
panic(fmt.Errorf("RegisterVTable '%s': invalid guid: %s", tName, err))
}
vTable := &vTable{
Parent: parent,
Name: tName,
ComGUID: comGuid.String(),
}
vTable.ComVTable, vTable.ComProcs = allocUintptrObject(parentProcsCount + len(fns))
for i, proc := range parentProcs {
vTable.ComProcs[i] = proc
}
for i, fn := range fns {
vTable.ComProcs[parentProcsCount+i] = windows.NewCallback(fn)
}
vTables[tName] = vTable
}
func typeInterfaceToString[T any]() (reflect.Type, string) {
t := reflect.TypeOf((*T)(nil))
if t.Kind() != reflect.Pointer {
panic("must be a (*yourInterfaceType)(nil)")
}
t = t.Elem()
return t, t.PkgPath() + "/" + t.Name()
}
func typeInterfaceToStringOnly[T any]() string {
_, nane := typeInterfaceToString[T]()
return nane
}
func guidOf[T any]() string {
vtable := vTableOf[T]()
if vtable == nil {
return ""
}
return vtable.ComGUID
}
func vTableOf[T any]() *vTable {
name := typeInterfaceToStringOnly[T]()
vTablesL.Lock()
defer vTablesL.Unlock()
return vTables[name]
}
type ifceImpl interface {
impl() any
ifce() (*vTable, error)
}
type ifceDef[T any] struct {
objImpl any
}
func (i ifceDef[T]) impl() any {
return i.objImpl
}
func (i ifceDef[T]) ifce() (*vTable, error) {
vtable := vTableOf[T]()
if vtable == nil {
return nil, fmt.Errorf("Unable to find vTable for %s", typeInterfaceToStringOnly[T]())
}
return vtable, nil
}

View File

@ -1,10 +0,0 @@
//go:build windows
package edge
type COREWEBVIEW2_COLOR struct {
A uint8
R uint8
G uint8
B uint8
}

View File

@ -1,11 +0,0 @@
//go:build windows
package edge
type COREWEBVIEW2_HOST_RESOURCE_ACCESS_KIND uint32
const (
COREWEBVIEW2_HOST_RESOURCE_ACCESS_KIND_DENY = iota
COREWEBVIEW2_HOST_RESOURCE_ACCESS_KIND_ALLOW
COREWEBVIEW2_HOST_RESOURCE_ACCESS_KIND_DENY_CORS
)

View File

@ -1,12 +0,0 @@
//go:build windows
package edge
type COREWEBVIEW2_KEY_EVENT_KIND uint32
const (
COREWEBVIEW2_KEY_EVENT_KIND_KEY_DOWN = 0
COREWEBVIEW2_KEY_EVENT_KIND_KEY_UP = 1
COREWEBVIEW2_KEY_EVENT_KIND_SYSTEM_KEY_DOWN = 2
COREWEBVIEW2_KEY_EVENT_KIND_SYSTEM_KEY_UP = 3
)

View File

@ -1,11 +0,0 @@
//go:build windows
package edge
type COREWEBVIEW2_MOVE_FOCUS_REASON uint32
const (
COREWEBVIEW2_MOVE_FOCUS_REASON_PROGRAMMATIC = 0
COREWEBVIEW2_MOVE_FOCUS_REASON_NEXT = 1
COREWEBVIEW2_MOVE_FOCUS_REASON_PREVIOUS = 2
)

View File

@ -1,12 +0,0 @@
//go:build windows
package edge
type COREWEBVIEW2_PHYSICAL_KEY_STATUS struct {
RepeatCount uint32
ScanCode uint32
IsExtendedKey bool
IsMenuKeyDown bool
WasKeyDown bool
IsKeyReleased bool
}

View File

@ -1,49 +0,0 @@
//go:build windows
package edge
type COREWEBVIEW2_PROCESS_FAILED_KIND uint32
const (
// Indicates that the browser process ended unexpectedly. The WebView
// automatically moves to the Closed state. The app has to recreate a new
// WebView to recover from this failure.
COREWEBVIEW2_PROCESS_FAILED_KIND_BROWSER_PROCESS_EXITED = 0
// Indicates that the main frame's render process ended unexpectedly. A new
// render process is created automatically and navigated to an error page.
// You can use the `Reload` method to try to reload the page that failed.
COREWEBVIEW2_PROCESS_FAILED_KIND_RENDER_PROCESS_EXITED = 1
// Indicates that the main frame's render process is unresponsive.
//
// Note that this does not seem to work right now.
// Does not fire for simple long running script case, the only related test
// SitePerProcessBrowserTest::NoCommitTimeoutForInvisibleWebContents is
// disabled.
COREWEBVIEW2_PROCESS_FAILED_KIND_RENDER_PROCESS_UNRESPONSIVE = 2
// Indicates that a frame-only render process ended unexpectedly. The process
// exit does not affect the top-level document, only a subset of the
// subframes within it. The content in these frames is replaced with an error
// page in the frame.
COREWEBVIEW2_PROCESS_FAILED_KIND_FRAME_RENDER_PROCESS_EXITED = 3
// Indicates that a utility process ended unexpectedly.
COREWEBVIEW2_PROCESS_FAILED_KIND_UTILITY_PROCESS_EXITED = 4
// Indicates that a sandbox helper process ended unexpectedly.
COREWEBVIEW2_PROCESS_FAILED_KIND_SANDBOX_HELPER_PROCESS_EXITED = 5
// Indicates that the GPU process ended unexpectedly.
COREWEBVIEW2_PROCESS_FAILED_KIND_GPU_PROCESS_EXITED = 6
// Indicates that a PPAPI plugin process ended unexpectedly.
COREWEBVIEW2_PROCESS_FAILED_KIND_PPAPI_PLUGIN_PROCESS_EXITED = 7
// Indicates that a PPAPI plugin broker process ended unexpectedly.
COREWEBVIEW2_PROCESS_FAILED_KIND_PPAPI_BROKER_PROCESS_EXITED = 8
// Indicates that a process of unspecified kind ended unexpectedly.
COREWEBVIEW2_PROCESS_FAILED_KIND_UNKNOWN_PROCESS_EXITED = 9
)

View File

@ -1,25 +0,0 @@
//go:build windows
package edge
type COREWEBVIEW2_WEB_RESOURCE_CONTEXT uint32
const (
COREWEBVIEW2_WEB_RESOURCE_CONTEXT_ALL = 0
COREWEBVIEW2_WEB_RESOURCE_CONTEXT_DOCUMENT = 1
COREWEBVIEW2_WEB_RESOURCE_CONTEXT_STYLESHEET = 2
COREWEBVIEW2_WEB_RESOURCE_CONTEXT_IMAGE = 3
COREWEBVIEW2_WEB_RESOURCE_CONTEXT_MEDIA = 4
COREWEBVIEW2_WEB_RESOURCE_CONTEXT_FONT = 5
COREWEBVIEW2_WEB_RESOURCE_CONTEXT_SCRIPT = 6
COREWEBVIEW2_WEB_RESOURCE_CONTEXT_XML_HTTP_REQUEST = 7
COREWEBVIEW2_WEB_RESOURCE_CONTEXT_FETCH = 8
COREWEBVIEW2_WEB_RESOURCE_CONTEXT_TEXT_TRACK = 9
COREWEBVIEW2_WEB_RESOURCE_CONTEXT_EVENT_SOURCE = 10
COREWEBVIEW2_WEB_RESOURCE_CONTEXT_WEBSOCKET = 11
COREWEBVIEW2_WEB_RESOURCE_CONTEXT_MANIFEST = 12
COREWEBVIEW2_WEB_RESOURCE_CONTEXT_SIGNED_EXCHANGE = 13
COREWEBVIEW2_WEB_RESOURCE_CONTEXT_PING = 14
COREWEBVIEW2_WEB_RESOURCE_CONTEXT_CSP_VIOLATION_REPORT = 15
COREWEBVIEW2_WEB_RESOURCE_CONTEXT_OTHER = 16
)

View File

@ -1,79 +0,0 @@
//go:build windows
package edge
import (
"unsafe"
"golang.org/x/sys/windows"
)
type _ICoreWebView2AcceleratorKeyPressedEventArgsVtbl struct {
_IUnknownVtbl
GetKeyEventKind ComProc
GetVirtualKey ComProc
GetKeyEventLParam ComProc
GetPhysicalKeyStatus ComProc
GetHandled ComProc
PutHandled ComProc
}
type ICoreWebView2AcceleratorKeyPressedEventArgs struct {
vtbl *_ICoreWebView2AcceleratorKeyPressedEventArgsVtbl
}
func (i *ICoreWebView2AcceleratorKeyPressedEventArgs) AddRef() uintptr {
return i.AddRef()
}
func (i *ICoreWebView2AcceleratorKeyPressedEventArgs) GetKeyEventKind() (COREWEBVIEW2_KEY_EVENT_KIND, error) {
var err error
var keyEventKind COREWEBVIEW2_KEY_EVENT_KIND
_, _, err = i.vtbl.GetKeyEventKind.Call(
uintptr(unsafe.Pointer(i)),
uintptr(unsafe.Pointer(&keyEventKind)),
)
if err != windows.ERROR_SUCCESS {
return 0, err
}
return keyEventKind, nil
}
func (i *ICoreWebView2AcceleratorKeyPressedEventArgs) GetVirtualKey() (uint, error) {
var err error
var virtualKey uint
_, _, err = i.vtbl.GetVirtualKey.Call(
uintptr(unsafe.Pointer(i)),
uintptr(unsafe.Pointer(&virtualKey)),
)
if err != windows.ERROR_SUCCESS {
return 0, err
}
return virtualKey, nil
}
func (i *ICoreWebView2AcceleratorKeyPressedEventArgs) GetPhysicalKeyStatus() (COREWEBVIEW2_PHYSICAL_KEY_STATUS, error) {
var err error
var physicalKeyStatus COREWEBVIEW2_PHYSICAL_KEY_STATUS
_, _, err = i.vtbl.GetPhysicalKeyStatus.Call(
uintptr(unsafe.Pointer(i)),
uintptr(unsafe.Pointer(&physicalKeyStatus)),
)
if err != windows.ERROR_SUCCESS {
return COREWEBVIEW2_PHYSICAL_KEY_STATUS{}, err
}
return physicalKeyStatus, nil
}
func (i *ICoreWebView2AcceleratorKeyPressedEventArgs) PutHandled(handled bool) error {
var err error
_, _, err = i.vtbl.PutHandled.Call(
uintptr(unsafe.Pointer(i)),
uintptr(boolToInt(handled)),
)
if err != windows.ERROR_SUCCESS {
return err
}
return nil
}

View File

@ -1,53 +0,0 @@
//go:build windows
package edge
type _ICoreWebView2AcceleratorKeyPressedEventHandlerVtbl struct {
_IUnknownVtbl
Invoke ComProc
}
type ICoreWebView2AcceleratorKeyPressedEventHandler struct {
vtbl *_ICoreWebView2AcceleratorKeyPressedEventHandlerVtbl
impl _ICoreWebView2AcceleratorKeyPressedEventHandlerImpl
}
func (i *ICoreWebView2AcceleratorKeyPressedEventHandler) AddRef() uintptr {
return i.AddRef()
}
func _ICoreWebView2AcceleratorKeyPressedEventHandlerIUnknownQueryInterface(this *ICoreWebView2AcceleratorKeyPressedEventHandler, refiid, object uintptr) uintptr {
return this.impl.QueryInterface(refiid, object)
}
func _ICoreWebView2AcceleratorKeyPressedEventHandlerIUnknownAddRef(this *ICoreWebView2AcceleratorKeyPressedEventHandler) uintptr {
return this.impl.AddRef()
}
func _ICoreWebView2AcceleratorKeyPressedEventHandlerIUnknownRelease(this *ICoreWebView2AcceleratorKeyPressedEventHandler) uintptr {
return this.impl.Release()
}
func _ICoreWebView2AcceleratorKeyPressedEventHandlerInvoke(this *ICoreWebView2AcceleratorKeyPressedEventHandler, sender *ICoreWebView2Controller, args *ICoreWebView2AcceleratorKeyPressedEventArgs) uintptr {
return this.impl.AcceleratorKeyPressed(sender, args)
}
type _ICoreWebView2AcceleratorKeyPressedEventHandlerImpl interface {
_IUnknownImpl
AcceleratorKeyPressed(sender *ICoreWebView2Controller, args *ICoreWebView2AcceleratorKeyPressedEventArgs) uintptr
}
var _ICoreWebView2AcceleratorKeyPressedEventHandlerFn = _ICoreWebView2AcceleratorKeyPressedEventHandlerVtbl{
_IUnknownVtbl{
NewComProc(_ICoreWebView2AcceleratorKeyPressedEventHandlerIUnknownQueryInterface),
NewComProc(_ICoreWebView2AcceleratorKeyPressedEventHandlerIUnknownAddRef),
NewComProc(_ICoreWebView2AcceleratorKeyPressedEventHandlerIUnknownRelease),
},
NewComProc(_ICoreWebView2AcceleratorKeyPressedEventHandlerInvoke),
}
func newICoreWebView2AcceleratorKeyPressedEventHandler(impl _ICoreWebView2AcceleratorKeyPressedEventHandlerImpl) *ICoreWebView2AcceleratorKeyPressedEventHandler {
return &ICoreWebView2AcceleratorKeyPressedEventHandler{
vtbl: &_ICoreWebView2AcceleratorKeyPressedEventHandlerFn,
impl: impl,
}
}

View File

@ -1,160 +0,0 @@
//go:build windows
package edge
import (
"math"
"unsafe"
"github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/go-webview2/internal/w32"
"golang.org/x/sys/windows"
)
type _ICoreWebView2ControllerVtbl struct {
_IUnknownVtbl
GetIsVisible ComProc
PutIsVisible ComProc
GetBounds ComProc
PutBounds ComProc
GetZoomFactor ComProc
PutZoomFactor ComProc
AddZoomFactorChanged ComProc
RemoveZoomFactorChanged ComProc
SetBoundsAndZoomFactor ComProc
MoveFocus ComProc
AddMoveFocusRequested ComProc
RemoveMoveFocusRequested ComProc
AddGotFocus ComProc
RemoveGotFocus ComProc
AddLostFocus ComProc
RemoveLostFocus ComProc
AddAcceleratorKeyPressed ComProc
RemoveAcceleratorKeyPressed ComProc
GetParentWindow ComProc
PutParentWindow ComProc
NotifyParentWindowPositionChanged ComProc
Close ComProc
GetCoreWebView2 ComProc
}
type ICoreWebView2Controller struct {
vtbl *_ICoreWebView2ControllerVtbl
}
func (i *ICoreWebView2Controller) AddRef() uintptr {
return i.AddRef()
}
func (i *ICoreWebView2Controller) GetBounds() (*w32.Rect, error) {
var err error
var bounds w32.Rect
_, _, err = i.vtbl.GetBounds.Call(
uintptr(unsafe.Pointer(i)),
uintptr(unsafe.Pointer(&bounds)),
)
if err != windows.ERROR_SUCCESS {
return nil, err
}
return &bounds, nil
}
func (i *ICoreWebView2Controller) PutBounds(bounds w32.Rect) error {
var err error
_, _, err = i.vtbl.PutBounds.Call(
uintptr(unsafe.Pointer(i)),
uintptr(unsafe.Pointer(&bounds)),
)
if err != windows.ERROR_SUCCESS {
return err
}
return nil
}
func (i *ICoreWebView2Controller) MoveFocus(reason COREWEBVIEW2_MOVE_FOCUS_REASON) error {
var err error
_, _, err = i.vtbl.MoveFocus.Call(
uintptr(unsafe.Pointer(i)),
uintptr(reason),
)
if err != windows.ERROR_SUCCESS {
return err
}
return nil
}
func (i *ICoreWebView2Controller) AddAcceleratorKeyPressed(eventHandler *ICoreWebView2AcceleratorKeyPressedEventHandler, token *_EventRegistrationToken) error {
var err error
_, _, err = i.vtbl.AddAcceleratorKeyPressed.Call(
uintptr(unsafe.Pointer(i)),
uintptr(unsafe.Pointer(eventHandler)),
uintptr(unsafe.Pointer(&token)),
)
if err != windows.ERROR_SUCCESS {
return err
}
return nil
}
func (i *ICoreWebView2Controller) PutIsVisible(isVisible bool) error {
var err error
_, _, err = i.vtbl.PutIsVisible.Call(
uintptr(unsafe.Pointer(i)),
uintptr(boolToInt(isVisible)),
)
if err != windows.ERROR_SUCCESS {
return err
}
return nil
}
func (i *ICoreWebView2Controller) GetICoreWebView2Controller2() *ICoreWebView2Controller2 {
var result *ICoreWebView2Controller2
iidICoreWebView2Controller2 := NewGUID("{c979903e-d4ca-4228-92eb-47ee3fa96eab}")
i.vtbl.QueryInterface.Call(
uintptr(unsafe.Pointer(i)),
uintptr(unsafe.Pointer(iidICoreWebView2Controller2)),
uintptr(unsafe.Pointer(&result)))
return result
}
func (i *ICoreWebView2Controller) NotifyParentWindowPositionChanged() error {
var err error
_, _, err = i.vtbl.NotifyParentWindowPositionChanged.Call(
uintptr(unsafe.Pointer(i)),
)
if err != windows.ERROR_SUCCESS {
return err
}
return nil
}
func (i *ICoreWebView2Controller) PutZoomFactor(zoomFactor float64) error {
var err error
_, _, err = i.vtbl.PutZoomFactor.Call(
uintptr(unsafe.Pointer(i)),
uintptr(math.Float64bits(zoomFactor)),
)
if err != windows.ERROR_SUCCESS {
return err
}
return nil
}
func (i *ICoreWebView2Controller) GetZoomFactor() (float64, error) {
var err error
var zoomFactorUint64 uint64
_, _, err = i.vtbl.GetZoomFactor.Call(
uintptr(unsafe.Pointer(i)),
uintptr(unsafe.Pointer(&zoomFactorUint64)),
)
if err != windows.ERROR_SUCCESS {
return 0.0, err
}
return math.Float64frombits(zoomFactorUint64), nil
}

View File

@ -1,75 +0,0 @@
//go:build windows
package edge
import (
"unsafe"
"golang.org/x/sys/windows"
)
type _ICoreWebView2Controller2Vtbl struct {
_IUnknownVtbl
GetIsVisible ComProc
PutIsVisible ComProc
GetBounds ComProc
PutBounds ComProc
GetZoomFactor ComProc
PutZoomFactor ComProc
AddZoomFactorChanged ComProc
RemoveZoomFactorChanged ComProc
SetBoundsAndZoomFactor ComProc
MoveFocus ComProc
AddMoveFocusRequested ComProc
RemoveMoveFocusRequested ComProc
AddGotFocus ComProc
RemoveGotFocus ComProc
AddLostFocus ComProc
RemoveLostFocus ComProc
AddAcceleratorKeyPressed ComProc
RemoveAcceleratorKeyPressed ComProc
GetParentWindow ComProc
PutParentWindow ComProc
NotifyParentWindowPositionChanged ComProc
Close ComProc
GetCoreWebView2 ComProc
GetDefaultBackgroundColor ComProc
PutDefaultBackgroundColor ComProc
}
type ICoreWebView2Controller2 struct {
vtbl *_ICoreWebView2Controller2Vtbl
}
func (i *ICoreWebView2Controller2) AddRef() uintptr {
return i.AddRef()
}
func (i *ICoreWebView2Controller2) GetDefaultBackgroundColor() (*COREWEBVIEW2_COLOR, error) {
var err error
var backgroundColor *COREWEBVIEW2_COLOR
_, _, err = i.vtbl.GetDefaultBackgroundColor.Call(
uintptr(unsafe.Pointer(i)),
uintptr(unsafe.Pointer(&backgroundColor)),
)
if err != windows.ERROR_SUCCESS {
return nil, err
}
return backgroundColor, nil
}
func (i *ICoreWebView2Controller2) PutDefaultBackgroundColor(backgroundColor COREWEBVIEW2_COLOR) error {
var err error
// Cast to a uint32 as that's what the call is expecting
col := *(*uint32)(unsafe.Pointer(&backgroundColor))
_, _, err = i.vtbl.PutDefaultBackgroundColor.Call(
uintptr(unsafe.Pointer(i)),
uintptr(col),
)
if err != windows.ERROR_SUCCESS {
return err
}
return nil
}

View File

@ -1,53 +0,0 @@
//go:build windows
package edge
type _ICoreWebView2CreateCoreWebView2ControllerCompletedHandlerVtbl struct {
_IUnknownVtbl
Invoke ComProc
}
type iCoreWebView2CreateCoreWebView2ControllerCompletedHandler struct {
vtbl *_ICoreWebView2CreateCoreWebView2ControllerCompletedHandlerVtbl
impl _ICoreWebView2CreateCoreWebView2ControllerCompletedHandlerImpl
}
func (i *iCoreWebView2CreateCoreWebView2ControllerCompletedHandler) AddRef() uintptr {
return i.AddRef()
}
func _ICoreWebView2CreateCoreWebView2ControllerCompletedHandlerIUnknownQueryInterface(this *iCoreWebView2CreateCoreWebView2ControllerCompletedHandler, refiid, object uintptr) uintptr {
return this.impl.QueryInterface(refiid, object)
}
func _ICoreWebView2CreateCoreWebView2ControllerCompletedHandlerIUnknownAddRef(this *iCoreWebView2CreateCoreWebView2ControllerCompletedHandler) uintptr {
return this.impl.AddRef()
}
func _ICoreWebView2CreateCoreWebView2ControllerCompletedHandlerIUnknownRelease(this *iCoreWebView2CreateCoreWebView2ControllerCompletedHandler) uintptr {
return this.impl.Release()
}
func _ICoreWebView2CreateCoreWebView2ControllerCompletedHandlerInvoke(this *iCoreWebView2CreateCoreWebView2ControllerCompletedHandler, errorCode uintptr, createdController *ICoreWebView2Controller) uintptr {
return this.impl.CreateCoreWebView2ControllerCompleted(errorCode, createdController)
}
type _ICoreWebView2CreateCoreWebView2ControllerCompletedHandlerImpl interface {
_IUnknownImpl
CreateCoreWebView2ControllerCompleted(errorCode uintptr, createdController *ICoreWebView2Controller) uintptr
}
var _ICoreWebView2CreateCoreWebView2ControllerCompletedHandlerFn = _ICoreWebView2CreateCoreWebView2ControllerCompletedHandlerVtbl{
_IUnknownVtbl{
NewComProc(_ICoreWebView2CreateCoreWebView2ControllerCompletedHandlerIUnknownQueryInterface),
NewComProc(_ICoreWebView2CreateCoreWebView2ControllerCompletedHandlerIUnknownAddRef),
NewComProc(_ICoreWebView2CreateCoreWebView2ControllerCompletedHandlerIUnknownRelease),
},
NewComProc(_ICoreWebView2CreateCoreWebView2ControllerCompletedHandlerInvoke),
}
func newICoreWebView2CreateCoreWebView2ControllerCompletedHandler(impl _ICoreWebView2CreateCoreWebView2ControllerCompletedHandlerImpl) *iCoreWebView2CreateCoreWebView2ControllerCompletedHandler {
return &iCoreWebView2CreateCoreWebView2ControllerCompletedHandler{
vtbl: &_ICoreWebView2CreateCoreWebView2ControllerCompletedHandlerFn,
impl: impl,
}
}

View File

@ -1,78 +0,0 @@
//go:build windows
package edge
import (
"syscall"
"unsafe"
"golang.org/x/sys/windows"
)
type _ICoreWebView2HttpHeadersCollectionIteratorVtbl struct {
_IUnknownVtbl
GetCurrentHeader ComProc
GetHasCurrentHeader ComProc
MoveNext ComProc
}
type ICoreWebView2HttpHeadersCollectionIterator struct {
vtbl *_ICoreWebView2HttpHeadersCollectionIteratorVtbl
}
func (i *ICoreWebView2HttpHeadersCollectionIterator) Release() error {
return i.vtbl.CallRelease(unsafe.Pointer(i))
}
func (i *ICoreWebView2HttpHeadersCollectionIterator) HasCurrentHeader() (bool, error) {
var hasHeader int32
res, _, err := i.vtbl.GetHasCurrentHeader.Call(
uintptr(unsafe.Pointer(i)),
uintptr(unsafe.Pointer(&hasHeader)),
)
if err != windows.ERROR_SUCCESS {
return false, err
}
if windows.Handle(res) != windows.S_OK {
return false, syscall.Errno(res)
}
return hasHeader != 0, nil
}
func (i *ICoreWebView2HttpHeadersCollectionIterator) GetCurrentHeader() (string, string, error) {
// Create *uint16 to hold result
var _name *uint16
var _value *uint16
res, _, err := i.vtbl.GetCurrentHeader.Call(
uintptr(unsafe.Pointer(i)),
uintptr(unsafe.Pointer(&_name)),
uintptr(unsafe.Pointer(&_value)),
)
if err != windows.ERROR_SUCCESS {
return "", "", err
}
if windows.Handle(res) != windows.S_OK {
return "", "", syscall.Errno(res)
}
// Get result and cleanup
name := windows.UTF16PtrToString(_name)
windows.CoTaskMemFree(unsafe.Pointer(_name))
value := windows.UTF16PtrToString(_value)
windows.CoTaskMemFree(unsafe.Pointer(_value))
return name, value, nil
}
func (i *ICoreWebView2HttpHeadersCollectionIterator) MoveNext() (bool, error) {
var next int32
res, _, err := i.vtbl.MoveNext.Call(
uintptr(unsafe.Pointer(i)),
uintptr(unsafe.Pointer(&next)),
)
if err != windows.ERROR_SUCCESS {
return false, err
}
if windows.Handle(res) != windows.S_OK {
return false, syscall.Errno(res)
}
return next != 0, nil
}

View File

@ -1,101 +0,0 @@
//go:build windows
package edge
import (
"syscall"
"unsafe"
"golang.org/x/sys/windows"
)
const (
ERROR_ELEMENT_NOT_FOUND syscall.Errno = 0x80070490
)
type _ICoreWebView2HttpRequestHeadersVtbl struct {
_IUnknownVtbl
GetHeader ComProc
GetHeaders ComProc
Contains ComProc
SetHeader ComProc
RemoveHeader ComProc
GetIterator ComProc
}
type ICoreWebView2HttpRequestHeaders struct {
vtbl *_ICoreWebView2HttpRequestHeadersVtbl
}
func (i *ICoreWebView2HttpRequestHeaders) Release() error {
return i.vtbl.CallRelease(unsafe.Pointer(i))
}
// GetHeader returns the value of the specified header. If the header is not found
// ERROR_ELEMENT_NOT_FOUND is returned as error.
func (i *ICoreWebView2HttpRequestHeaders) GetHeader(name string) (string, error) {
_name, err := windows.UTF16PtrFromString(name)
if err != nil {
return "", nil
}
var _value *uint16
res, _, err := i.vtbl.GetHeader.Call(
uintptr(unsafe.Pointer(i)),
uintptr(unsafe.Pointer(_name)),
uintptr(unsafe.Pointer(&_value)),
)
if err != windows.ERROR_SUCCESS {
return "", err
}
if windows.Handle(res) != windows.S_OK {
return "", syscall.Errno(res)
}
value := windows.UTF16PtrToString(_value)
windows.CoTaskMemFree(unsafe.Pointer(_value))
return value, nil
}
// SetHeader sets the specified header to the value.
func (i *ICoreWebView2HttpRequestHeaders) SetHeader(name, value string) error {
_name, err := windows.UTF16PtrFromString(name)
if err != nil {
return nil
}
_value, err := windows.UTF16PtrFromString(value)
if err != nil {
return nil
}
res, _, err := i.vtbl.SetHeader.Call(
uintptr(unsafe.Pointer(i)),
uintptr(unsafe.Pointer(_name)),
uintptr(unsafe.Pointer(_value)),
)
if err != windows.ERROR_SUCCESS {
return err
}
if windows.Handle(res) != windows.S_OK {
return syscall.Errno(res)
}
return nil
}
// GetIterator returns an iterator over the collection of request headers. Make sure to call
// Release on the returned Object after finished using it.
func (i *ICoreWebView2HttpRequestHeaders) GetIterator() (*ICoreWebView2HttpHeadersCollectionIterator, error) {
var headers *ICoreWebView2HttpHeadersCollectionIterator
res, _, err := i.vtbl.GetIterator.Call(
uintptr(unsafe.Pointer(i)),
uintptr(unsafe.Pointer(&headers)),
)
if err != windows.ERROR_SUCCESS {
return nil, err
}
if windows.Handle(res) != windows.S_OK {
return nil, syscall.Errno(res)
}
return headers, nil
}

View File

@ -1,18 +0,0 @@
//go:build windows
package edge
type _ICoreWebView2NavigationCompletedEventArgsVtbl struct {
_IUnknownVtbl
GetIsSuccess ComProc
GetWebErrorStatus ComProc
GetNavigationId ComProc
}
type ICoreWebView2NavigationCompletedEventArgs struct {
vtbl *_ICoreWebView2NavigationCompletedEventArgsVtbl
}
func (i *ICoreWebView2NavigationCompletedEventArgs) AddRef() uintptr {
return i.AddRef()
}

View File

@ -1,53 +0,0 @@
//go:build windows
package edge
type _ICoreWebView2NavigationCompletedEventHandlerVtbl struct {
_IUnknownVtbl
Invoke ComProc
}
type ICoreWebView2NavigationCompletedEventHandler struct {
vtbl *_ICoreWebView2NavigationCompletedEventHandlerVtbl
impl _ICoreWebView2NavigationCompletedEventHandlerImpl
}
func (i *ICoreWebView2NavigationCompletedEventHandler) AddRef() uintptr {
return i.AddRef()
}
func _ICoreWebView2NavigationCompletedEventHandlerIUnknownQueryInterface(this *ICoreWebView2NavigationCompletedEventHandler, refiid, object uintptr) uintptr {
return this.impl.QueryInterface(refiid, object)
}
func _ICoreWebView2NavigationCompletedEventHandlerIUnknownAddRef(this *ICoreWebView2NavigationCompletedEventHandler) uintptr {
return this.impl.AddRef()
}
func _ICoreWebView2NavigationCompletedEventHandlerIUnknownRelease(this *ICoreWebView2NavigationCompletedEventHandler) uintptr {
return this.impl.Release()
}
func _ICoreWebView2NavigationCompletedEventHandlerInvoke(this *ICoreWebView2NavigationCompletedEventHandler, sender *ICoreWebView2, args *ICoreWebView2NavigationCompletedEventArgs) uintptr {
return this.impl.NavigationCompleted(sender, args)
}
type _ICoreWebView2NavigationCompletedEventHandlerImpl interface {
_IUnknownImpl
NavigationCompleted(sender *ICoreWebView2, args *ICoreWebView2NavigationCompletedEventArgs) uintptr
}
var _ICoreWebView2NavigationCompletedEventHandlerFn = _ICoreWebView2NavigationCompletedEventHandlerVtbl{
_IUnknownVtbl{
NewComProc(_ICoreWebView2NavigationCompletedEventHandlerIUnknownQueryInterface),
NewComProc(_ICoreWebView2NavigationCompletedEventHandlerIUnknownAddRef),
NewComProc(_ICoreWebView2NavigationCompletedEventHandlerIUnknownRelease),
},
NewComProc(_ICoreWebView2NavigationCompletedEventHandlerInvoke),
}
func newICoreWebView2NavigationCompletedEventHandler(impl _ICoreWebView2NavigationCompletedEventHandlerImpl) *ICoreWebView2NavigationCompletedEventHandler {
return &ICoreWebView2NavigationCompletedEventHandler{
vtbl: &_ICoreWebView2NavigationCompletedEventHandlerFn,
impl: impl,
}
}

View File

@ -1,41 +0,0 @@
//go:build windows
package edge
import (
"fmt"
"syscall"
"unsafe"
"golang.org/x/sys/windows"
)
type _ICoreWebView2ProcessFailedEventArgsVtbl struct {
_IUnknownVtbl
GetProcessFailedKind ComProc
}
type ICoreWebView2ProcessFailedEventArgs struct {
vtbl *_ICoreWebView2ProcessFailedEventArgsVtbl
}
func (i *ICoreWebView2ProcessFailedEventArgs) GetProcessFailedKind() (COREWEBVIEW2_PROCESS_FAILED_KIND, error) {
kind := COREWEBVIEW2_PROCESS_FAILED_KIND(0xffffffff)
hr, _, err := i.vtbl.GetProcessFailedKind.Call(
uintptr(unsafe.Pointer(i)),
uintptr(unsafe.Pointer(&kind)),
)
if windows.Handle(hr) != windows.S_OK {
return 0, syscall.Errno(hr)
}
if kind == 0xffffffff {
if err == nil {
err = fmt.Errorf("unknown error")
}
return 0, err
}
return kind, nil
}

View File

@ -1,53 +0,0 @@
//go:build windows
package edge
type _ICoreWebView2ProcessFailedEventHandlerVtbl struct {
_IUnknownVtbl
Invoke ComProc
}
type ICoreWebView2ProcessFailedEventHandler struct {
vtbl *_ICoreWebView2ProcessFailedEventHandlerVtbl
impl _ICoreWebView2ProcessFailedEventHandlerImpl
}
func (i *ICoreWebView2ProcessFailedEventHandler) AddRef() uintptr {
return i.AddRef()
}
func _ICoreWebView2ProcessFailedEventHandlerIUnknownQueryInterface(this *ICoreWebView2ProcessFailedEventHandler, refiid, object uintptr) uintptr {
return this.impl.QueryInterface(refiid, object)
}
func _ICoreWebView2ProcessFailedEventHandlerIUnknownAddRef(this *ICoreWebView2ProcessFailedEventHandler) uintptr {
return this.impl.AddRef()
}
func _ICoreWebView2ProcessFailedEventHandlerIUnknownRelease(this *ICoreWebView2ProcessFailedEventHandler) uintptr {
return this.impl.Release()
}
func _ICoreWebView2ProcessFailedEventHandlerInvoke(this *ICoreWebView2ProcessFailedEventHandler, sender *ICoreWebView2, args *ICoreWebView2ProcessFailedEventArgs) uintptr {
return this.impl.ProcessFailed(sender, args)
}
type _ICoreWebView2ProcessFailedEventHandlerImpl interface {
_IUnknownImpl
ProcessFailed(sender *ICoreWebView2, args *ICoreWebView2ProcessFailedEventArgs) uintptr
}
var _ICoreWebView2ProcessFailedEventHandlerFn = _ICoreWebView2ProcessFailedEventHandlerVtbl{
_IUnknownVtbl{
NewComProc(_ICoreWebView2ProcessFailedEventHandlerIUnknownQueryInterface),
NewComProc(_ICoreWebView2ProcessFailedEventHandlerIUnknownAddRef),
NewComProc(_ICoreWebView2ProcessFailedEventHandlerIUnknownRelease),
},
NewComProc(_ICoreWebView2ProcessFailedEventHandlerInvoke),
}
func newICoreWebView2ProcessFailedEventHandler(impl _ICoreWebView2ProcessFailedEventHandlerImpl) *ICoreWebView2ProcessFailedEventHandler {
return &ICoreWebView2ProcessFailedEventHandler{
vtbl: &_ICoreWebView2ProcessFailedEventHandlerFn,
impl: impl,
}
}

View File

@ -1,271 +0,0 @@
//go:build windows
package edge
import (
"unsafe"
"golang.org/x/sys/windows"
)
type _ICoreWebView2SettingsVtbl struct {
_IUnknownVtbl
GetIsScriptEnabled ComProc
PutIsScriptEnabled ComProc
GetIsWebMessageEnabled ComProc
PutIsWebMessageEnabled ComProc
GetAreDefaultScriptDialogsEnabled ComProc
PutAreDefaultScriptDialogsEnabled ComProc
GetIsStatusBarEnabled ComProc
PutIsStatusBarEnabled ComProc
GetAreDevToolsEnabled ComProc
PutAreDevToolsEnabled ComProc
GetAreDefaultContextMenusEnabled ComProc
PutAreDefaultContextMenusEnabled ComProc
GetAreHostObjectsAllowed ComProc
PutAreHostObjectsAllowed ComProc
GetIsZoomControlEnabled ComProc
PutIsZoomControlEnabled ComProc
GetIsBuiltInErrorPageEnabled ComProc
PutIsBuiltInErrorPageEnabled ComProc
}
type ICoreWebView2Settings struct {
vtbl *_ICoreWebView2SettingsVtbl
}
func (i *ICoreWebView2Settings) AddRef() uintptr {
return i.AddRef()
}
func (i *ICoreWebView2Settings) GetIsScriptEnabled() (bool, error) {
var err error
var isScriptEnabled bool
_, _, err = i.vtbl.GetIsScriptEnabled.Call(
uintptr(unsafe.Pointer(i)),
uintptr(unsafe.Pointer(&isScriptEnabled)),
)
if err != windows.ERROR_SUCCESS {
return false, err
}
return isScriptEnabled, nil
}
func (i *ICoreWebView2Settings) PutIsScriptEnabled(isScriptEnabled bool) error {
var err error
_, _, err = i.vtbl.PutIsScriptEnabled.Call(
uintptr(unsafe.Pointer(i)),
uintptr(boolToInt(isScriptEnabled)),
)
if err != windows.ERROR_SUCCESS {
return err
}
return nil
}
func (i *ICoreWebView2Settings) GetIsWebMessageEnabled() (bool, error) {
var err error
var isWebMessageEnabled bool
_, _, err = i.vtbl.GetIsWebMessageEnabled.Call(
uintptr(unsafe.Pointer(i)),
uintptr(unsafe.Pointer(&isWebMessageEnabled)),
)
if err != windows.ERROR_SUCCESS {
return false, err
}
return isWebMessageEnabled, nil
}
func (i *ICoreWebView2Settings) PutIsWebMessageEnabled(isWebMessageEnabled bool) error {
var err error
_, _, err = i.vtbl.PutIsWebMessageEnabled.Call(
uintptr(unsafe.Pointer(i)),
uintptr(boolToInt(isWebMessageEnabled)),
)
if err != windows.ERROR_SUCCESS {
return err
}
return nil
}
func (i *ICoreWebView2Settings) GetAreDefaultScriptDialogsEnabled() (bool, error) {
var err error
var areDefaultScriptDialogsEnabled bool
_, _, err = i.vtbl.GetAreDefaultScriptDialogsEnabled.Call(
uintptr(unsafe.Pointer(i)),
uintptr(unsafe.Pointer(&areDefaultScriptDialogsEnabled)),
)
if err != windows.ERROR_SUCCESS {
return false, err
}
return areDefaultScriptDialogsEnabled, nil
}
func (i *ICoreWebView2Settings) PutAreDefaultScriptDialogsEnabled(areDefaultScriptDialogsEnabled bool) error {
var err error
_, _, err = i.vtbl.PutAreDefaultScriptDialogsEnabled.Call(
uintptr(unsafe.Pointer(i)),
uintptr(boolToInt(areDefaultScriptDialogsEnabled)),
)
if err != windows.ERROR_SUCCESS {
return err
}
return nil
}
func (i *ICoreWebView2Settings) GetIsStatusBarEnabled() (bool, error) {
var err error
var isStatusBarEnabled bool
_, _, err = i.vtbl.GetIsStatusBarEnabled.Call(
uintptr(unsafe.Pointer(i)),
uintptr(unsafe.Pointer(&isStatusBarEnabled)),
)
if err != windows.ERROR_SUCCESS {
return false, err
}
return isStatusBarEnabled, nil
}
func (i *ICoreWebView2Settings) PutIsStatusBarEnabled(isStatusBarEnabled bool) error {
var err error
_, _, err = i.vtbl.PutIsStatusBarEnabled.Call(
uintptr(unsafe.Pointer(i)),
uintptr(boolToInt(isStatusBarEnabled)),
)
if err != windows.ERROR_SUCCESS {
return err
}
return nil
}
func (i *ICoreWebView2Settings) GetAreDevToolsEnabled() (bool, error) {
var err error
var areDevToolsEnabled bool
_, _, err = i.vtbl.GetAreDevToolsEnabled.Call(
uintptr(unsafe.Pointer(i)),
uintptr(unsafe.Pointer(&areDevToolsEnabled)),
)
if err != windows.ERROR_SUCCESS {
return false, err
}
return areDevToolsEnabled, nil
}
func (i *ICoreWebView2Settings) PutAreDevToolsEnabled(areDevToolsEnabled bool) error {
var err error
_, _, err = i.vtbl.PutAreDevToolsEnabled.Call(
uintptr(unsafe.Pointer(i)),
uintptr(boolToInt(areDevToolsEnabled)),
)
if err != windows.ERROR_SUCCESS {
return err
}
return nil
}
func (i *ICoreWebView2Settings) GetAreDefaultContextMenusEnabled() (bool, error) {
var err error
var enabled bool
_, _, err = i.vtbl.GetAreDefaultContextMenusEnabled.Call(
uintptr(unsafe.Pointer(i)),
uintptr(unsafe.Pointer(&enabled)),
)
if err != windows.ERROR_SUCCESS {
return false, err
}
return enabled, nil
}
func (i *ICoreWebView2Settings) PutAreDefaultContextMenusEnabled(enabled bool) error {
var err error
_, _, err = i.vtbl.PutAreDefaultContextMenusEnabled.Call(
uintptr(unsafe.Pointer(i)),
uintptr(boolToInt(enabled)),
)
if err != windows.ERROR_SUCCESS {
return err
}
return nil
}
func (i *ICoreWebView2Settings) GetAreHostObjectsAllowed() (bool, error) {
var err error
var allowed bool
_, _, err = i.vtbl.GetAreHostObjectsAllowed.Call(
uintptr(unsafe.Pointer(i)),
uintptr(unsafe.Pointer(&allowed)),
)
if err != windows.ERROR_SUCCESS {
return false, err
}
return allowed, nil
}
func (i *ICoreWebView2Settings) PutAreHostObjectsAllowed(allowed bool) error {
var err error
_, _, err = i.vtbl.PutAreHostObjectsAllowed.Call(
uintptr(unsafe.Pointer(i)),
uintptr(boolToInt(allowed)),
)
if err != windows.ERROR_SUCCESS {
return err
}
return nil
}
func (i *ICoreWebView2Settings) GetIsZoomControlEnabled() (bool, error) {
var err error
var enabled bool
_, _, err = i.vtbl.GetIsZoomControlEnabled.Call(
uintptr(unsafe.Pointer(i)),
uintptr(unsafe.Pointer(&enabled)),
)
if err != windows.ERROR_SUCCESS {
return false, err
}
return enabled, nil
}
func (i *ICoreWebView2Settings) PutIsZoomControlEnabled(enabled bool) error {
var err error
_, _, err = i.vtbl.PutIsZoomControlEnabled.Call(
uintptr(unsafe.Pointer(i)),
uintptr(boolToInt(enabled)),
)
if err != windows.ERROR_SUCCESS {
return err
}
return nil
}
func (i *ICoreWebView2Settings) GetIsBuiltInErrorPageEnabled() (bool, error) {
var err error
var enabled bool
_, _, err = i.vtbl.GetIsBuiltInErrorPageEnabled.Call(
uintptr(unsafe.Pointer(i)),
uintptr(unsafe.Pointer(&enabled)),
)
if err != windows.ERROR_SUCCESS {
return false, err
}
return enabled, nil
}
func (i *ICoreWebView2Settings) PutIsBuiltInErrorPageEnabled(enabled bool) error {
var err error
_, _, err = i.vtbl.PutIsBuiltInErrorPageEnabled.Call(
uintptr(unsafe.Pointer(i)),
uintptr(boolToInt(enabled)),
)
if err != windows.ERROR_SUCCESS {
return err
}
return nil
}

View File

@ -1,102 +0,0 @@
//go:build windows
package edge
import (
"syscall"
"unsafe"
"golang.org/x/sys/windows"
)
type _ICoreWebView2WebResourceRequestVtbl struct {
_IUnknownVtbl
GetUri ComProc
PutUri ComProc
GetMethod ComProc
PutMethod ComProc
GetContent ComProc
PutContent ComProc
GetHeaders ComProc
}
type ICoreWebView2WebResourceRequest struct {
vtbl *_ICoreWebView2WebResourceRequestVtbl
}
func (i *ICoreWebView2WebResourceRequest) AddRef() uintptr {
return i.AddRef()
}
func (i *ICoreWebView2WebResourceRequest) GetMethod() (string, error) {
// Create *uint16 to hold result
var _method *uint16
res, _, err := i.vtbl.GetMethod.Call(
uintptr(unsafe.Pointer(i)),
uintptr(unsafe.Pointer(&_method)),
)
if err != windows.ERROR_SUCCESS {
return "", err
}
if windows.Handle(res) != windows.S_OK {
return "", syscall.Errno(res)
}
// Get result and cleanup
uri := windows.UTF16PtrToString(_method)
windows.CoTaskMemFree(unsafe.Pointer(_method))
return uri, nil
}
func (i *ICoreWebView2WebResourceRequest) GetUri() (string, error) {
var err error
// Create *uint16 to hold result
var _uri *uint16
_, _, err = i.vtbl.GetUri.Call(
uintptr(unsafe.Pointer(i)),
uintptr(unsafe.Pointer(&_uri)),
)
if err != windows.ERROR_SUCCESS {
return "", err
} // Get result and cleanup
uri := windows.UTF16PtrToString(_uri)
windows.CoTaskMemFree(unsafe.Pointer(_uri))
return uri, nil
}
// GetContent returns the body of the request. Returns nil if there's no body. Make sure to call
// Release on the returned IStream after finished using it.
func (i *ICoreWebView2WebResourceRequest) GetContent() (*IStream, error) {
var stream *IStream
res, _, err := i.vtbl.GetContent.Call(
uintptr(unsafe.Pointer(i)),
uintptr(unsafe.Pointer(&stream)),
)
if err != windows.ERROR_SUCCESS {
return nil, err
}
if windows.Handle(res) != windows.S_OK {
return nil, syscall.Errno(res)
}
return stream, nil
}
// GetHeaders returns the mutable HTTP request headers. Make sure to call
// Release on the returned Object after finished using it.
func (i *ICoreWebView2WebResourceRequest) GetHeaders() (*ICoreWebView2HttpRequestHeaders, error) {
var headers *ICoreWebView2HttpRequestHeaders
res, _, err := i.vtbl.GetHeaders.Call(
uintptr(unsafe.Pointer(i)),
uintptr(unsafe.Pointer(&headers)),
)
if err != windows.ERROR_SUCCESS {
return nil, err
}
if windows.Handle(res) != windows.S_OK {
return nil, syscall.Errno(res)
}
return headers, nil
}
func (i *ICoreWebView2WebResourceRequest) Release() error {
return i.vtbl.CallRelease(unsafe.Pointer(i))
}

View File

@ -1,52 +0,0 @@
//go:build windows
package edge
import (
"unsafe"
"golang.org/x/sys/windows"
)
type _ICoreWebView2WebResourceRequestedEventArgsVtbl struct {
_IUnknownVtbl
GetRequest ComProc
GetResponse ComProc
PutResponse ComProc
GetDeferral ComProc
GetResourceContext ComProc
}
type ICoreWebView2WebResourceRequestedEventArgs struct {
vtbl *_ICoreWebView2WebResourceRequestedEventArgsVtbl
}
func (i *ICoreWebView2WebResourceRequestedEventArgs) AddRef() uintptr {
return i.AddRef()
}
func (i *ICoreWebView2WebResourceRequestedEventArgs) PutResponse(response *ICoreWebView2WebResourceResponse) error {
var err error
_, _, err = i.vtbl.PutResponse.Call(
uintptr(unsafe.Pointer(i)),
uintptr(unsafe.Pointer(response)),
)
if err != windows.ERROR_SUCCESS {
return err
}
return nil
}
func (i *ICoreWebView2WebResourceRequestedEventArgs) GetRequest() (*ICoreWebView2WebResourceRequest, error) {
var err error
var request *ICoreWebView2WebResourceRequest
_, _, err = i.vtbl.GetRequest.Call(
uintptr(unsafe.Pointer(i)),
uintptr(unsafe.Pointer(&request)),
)
if err != windows.ERROR_SUCCESS {
return nil, err
}
return request, nil
}

View File

@ -1,50 +0,0 @@
//go:build windows
package edge
type _ICoreWebView2WebResourceRequestedEventHandlerVtbl struct {
_IUnknownVtbl
Invoke ComProc
}
type iCoreWebView2WebResourceRequestedEventHandler struct {
vtbl *_ICoreWebView2WebResourceRequestedEventHandlerVtbl
impl _ICoreWebView2WebResourceRequestedEventHandlerImpl
}
func _ICoreWebView2WebResourceRequestedEventHandlerIUnknownQueryInterface(this *iCoreWebView2WebResourceRequestedEventHandler, refiid, object uintptr) uintptr {
return this.impl.QueryInterface(refiid, object)
}
func _ICoreWebView2WebResourceRequestedEventHandlerIUnknownAddRef(this *iCoreWebView2WebResourceRequestedEventHandler) uintptr {
return this.impl.AddRef()
}
func _ICoreWebView2WebResourceRequestedEventHandlerIUnknownRelease(this *iCoreWebView2WebResourceRequestedEventHandler) uintptr {
return this.impl.Release()
}
func _ICoreWebView2WebResourceRequestedEventHandlerInvoke(this *iCoreWebView2WebResourceRequestedEventHandler, sender *ICoreWebView2, args *ICoreWebView2WebResourceRequestedEventArgs) uintptr {
return this.impl.WebResourceRequested(sender, args)
}
type _ICoreWebView2WebResourceRequestedEventHandlerImpl interface {
_IUnknownImpl
WebResourceRequested(sender *ICoreWebView2, args *ICoreWebView2WebResourceRequestedEventArgs) uintptr
}
var _ICoreWebView2WebResourceRequestedEventHandlerFn = _ICoreWebView2WebResourceRequestedEventHandlerVtbl{
_IUnknownVtbl{
NewComProc(_ICoreWebView2WebResourceRequestedEventHandlerIUnknownQueryInterface),
NewComProc(_ICoreWebView2WebResourceRequestedEventHandlerIUnknownAddRef),
NewComProc(_ICoreWebView2WebResourceRequestedEventHandlerIUnknownRelease),
},
NewComProc(_ICoreWebView2WebResourceRequestedEventHandlerInvoke),
}
func newICoreWebView2WebResourceRequestedEventHandler(impl _ICoreWebView2WebResourceRequestedEventHandlerImpl) *iCoreWebView2WebResourceRequestedEventHandler {
return &iCoreWebView2WebResourceRequestedEventHandler{
vtbl: &_ICoreWebView2WebResourceRequestedEventHandlerFn,
impl: impl,
}
}

View File

@ -1,28 +0,0 @@
//go:build windows
package edge
import "unsafe"
type _ICoreWebView2WebResourceResponseVtbl struct {
_IUnknownVtbl
GetContent ComProc
PutContent ComProc
GetHeaders ComProc
GetStatusCode ComProc
PutStatusCode ComProc
GetReasonPhrase ComProc
PutReasonPhrase ComProc
}
type ICoreWebView2WebResourceResponse struct {
vtbl *_ICoreWebView2WebResourceResponseVtbl
}
func (i *ICoreWebView2WebResourceResponse) AddRef() uintptr {
return i.AddRef()
}
func (i *ICoreWebView2WebResourceResponse) Release() error {
return i.vtbl.CallRelease(unsafe.Pointer(i))
}

View File

@ -1,18 +0,0 @@
//go:build windows
package edge
type iCoreWebView2_2Vtbl struct {
iCoreWebView2Vtbl
AddWebResourceResponseReceived ComProc
RemoveWebResourceResponseReceived ComProc
NavigateWithWebResourceRequest ComProc
AddDomContentLoaded ComProc
RemoveDomContentLoaded ComProc
GetCookieManager ComProc
GetEnvironment ComProc
}
type ICoreWebView2_2 struct {
vtbl *iCoreWebView2_2Vtbl
}

View File

@ -1,62 +0,0 @@
//go:build windows
package edge
import (
"unsafe"
"golang.org/x/sys/windows"
)
type iCoreWebView2_3Vtbl struct {
iCoreWebView2_2Vtbl
TrySuspend ComProc
Resume ComProc
GetIsSuspended ComProc
SetVirtualHostNameToFolderMapping ComProc
ClearVirtualHostNameToFolderMapping ComProc
}
type ICoreWebView2_3 struct {
vtbl *iCoreWebView2_3Vtbl
}
func (i *ICoreWebView2_3) SetVirtualHostNameToFolderMapping(hostName, folderPath string, accessKind COREWEBVIEW2_HOST_RESOURCE_ACCESS_KIND) error {
_hostName, err := windows.UTF16PtrFromString(hostName)
if err != nil {
return err
}
_folderPath, err := windows.UTF16PtrFromString(folderPath)
if err != nil {
return err
}
_, _, err = i.vtbl.SetVirtualHostNameToFolderMapping.Call(
uintptr(unsafe.Pointer(i)),
uintptr(unsafe.Pointer(_hostName)),
uintptr(unsafe.Pointer(_folderPath)),
uintptr(accessKind),
)
if err != windows.ERROR_SUCCESS {
return err
}
return nil
}
func (i *ICoreWebView2) GetICoreWebView2_3() *ICoreWebView2_3 {
var result *ICoreWebView2_3
iidICoreWebView2_3 := NewGUID("{A0D6DF20-3B92-416D-AA0C-437A9C727857}")
_, _, _ = i.vtbl.QueryInterface.Call(
uintptr(unsafe.Pointer(i)),
uintptr(unsafe.Pointer(iidICoreWebView2_3)),
uintptr(unsafe.Pointer(&result)))
return result
}
func (e *Chromium) GetICoreWebView2_3() *ICoreWebView2_3 {
return e.webview.GetICoreWebView2_3()
}

View File

@ -1,397 +0,0 @@
//go:build windows
package edge
import (
"unsafe"
"golang.org/x/sys/windows"
)
// ICoreWebviewSettings is the merged settings class
type _ICoreWebViewSettingsVtbl struct {
_IUnknownVtbl
GetIsScriptEnabled ComProc
PutIsScriptEnabled ComProc
GetIsWebMessageEnabled ComProc
PutIsWebMessageEnabled ComProc
GetAreDefaultScriptDialogsEnabled ComProc
PutAreDefaultScriptDialogsEnabled ComProc
GetIsStatusBarEnabled ComProc
PutIsStatusBarEnabled ComProc
GetAreDevToolsEnabled ComProc
PutAreDevToolsEnabled ComProc
GetAreDefaultContextMenusEnabled ComProc
PutAreDefaultContextMenusEnabled ComProc
GetAreHostObjectsAllowed ComProc
PutAreHostObjectsAllowed ComProc
GetIsZoomControlEnabled ComProc
PutIsZoomControlEnabled ComProc
GetIsBuiltInErrorPageEnabled ComProc
PutIsBuiltInErrorPageEnabled ComProc
GetUserAgent ComProc // ICoreWebView2Settings2: SDK 1.0.864.35
PutUserAgent ComProc
GetAreBrowserAcceleratorKeysEnabled ComProc // ICoreWebView2Settings3: SDK 1.0.864.35
PutAreBrowserAcceleratorKeysEnabled ComProc
GetIsPasswordAutosaveEnabled ComProc // ICoreWebView2Settings4: SDK 1.0.902.49
PutIsPasswordAutosaveEnabled ComProc
GetIsGeneralAutofillEnabled ComProc
PutIsGeneralAutofillEnabled ComProc
GetIsPinchZoomEnabled ComProc // ICoreWebView2Settings5: SDK 1.0.902.49
PutIsPinchZoomEnabled ComProc
GetIsSwipeNavigationEnabled ComProc // ICoreWebView2Settings6: SDK 1.0.992.28
PutIsSwipeNavigationEnabled ComProc
}
type ICoreWebViewSettings struct {
vtbl *_ICoreWebViewSettingsVtbl
}
func (i *ICoreWebViewSettings) AddRef() uintptr {
return i.AddRef()
}
func (i *ICoreWebViewSettings) GetIsScriptEnabled() (bool, error) {
var err error
var isScriptEnabled bool
_, _, err = i.vtbl.GetIsScriptEnabled.Call(
uintptr(unsafe.Pointer(i)),
uintptr(unsafe.Pointer(&isScriptEnabled)),
)
if err != windows.ERROR_SUCCESS {
return false, err
}
return isScriptEnabled, nil
}
func (i *ICoreWebViewSettings) PutIsScriptEnabled(isScriptEnabled bool) error {
var err error
_, _, err = i.vtbl.PutIsScriptEnabled.Call(
uintptr(unsafe.Pointer(i)),
uintptr(boolToInt(isScriptEnabled)),
)
if err != windows.ERROR_SUCCESS {
return err
}
return nil
}
func (i *ICoreWebViewSettings) GetIsWebMessageEnabled() (bool, error) {
var err error
var isWebMessageEnabled bool
_, _, err = i.vtbl.GetIsWebMessageEnabled.Call(
uintptr(unsafe.Pointer(i)),
uintptr(unsafe.Pointer(&isWebMessageEnabled)),
)
if err != windows.ERROR_SUCCESS {
return false, err
}
return isWebMessageEnabled, nil
}
func (i *ICoreWebViewSettings) PutIsWebMessageEnabled(isWebMessageEnabled bool) error {
var err error
_, _, err = i.vtbl.PutIsWebMessageEnabled.Call(
uintptr(unsafe.Pointer(i)),
uintptr(boolToInt(isWebMessageEnabled)),
)
if err != windows.ERROR_SUCCESS {
return err
}
return nil
}
func (i *ICoreWebViewSettings) GetAreDefaultScriptDialogsEnabled() (bool, error) {
var err error
var areDefaultScriptDialogsEnabled bool
_, _, err = i.vtbl.GetAreDefaultScriptDialogsEnabled.Call(
uintptr(unsafe.Pointer(i)),
uintptr(unsafe.Pointer(&areDefaultScriptDialogsEnabled)),
)
if err != windows.ERROR_SUCCESS {
return false, err
}
return areDefaultScriptDialogsEnabled, nil
}
func (i *ICoreWebViewSettings) PutAreDefaultScriptDialogsEnabled(areDefaultScriptDialogsEnabled bool) error {
var err error
_, _, err = i.vtbl.PutAreDefaultScriptDialogsEnabled.Call(
uintptr(unsafe.Pointer(i)),
uintptr(boolToInt(areDefaultScriptDialogsEnabled)),
)
if err != windows.ERROR_SUCCESS {
return err
}
return nil
}
func (i *ICoreWebViewSettings) GetIsStatusBarEnabled() (bool, error) {
var err error
var isStatusBarEnabled bool
_, _, err = i.vtbl.GetIsStatusBarEnabled.Call(
uintptr(unsafe.Pointer(i)),
uintptr(unsafe.Pointer(&isStatusBarEnabled)),
)
if err != windows.ERROR_SUCCESS {
return false, err
}
return isStatusBarEnabled, nil
}
func (i *ICoreWebViewSettings) PutIsStatusBarEnabled(isStatusBarEnabled bool) error {
var err error
_, _, err = i.vtbl.PutIsStatusBarEnabled.Call(
uintptr(unsafe.Pointer(i)),
uintptr(boolToInt(isStatusBarEnabled)),
)
if err != windows.ERROR_SUCCESS {
return err
}
return nil
}
func (i *ICoreWebViewSettings) GetAreDevToolsEnabled() (bool, error) {
var err error
var areDevToolsEnabled bool
_, _, err = i.vtbl.GetAreDevToolsEnabled.Call(
uintptr(unsafe.Pointer(i)),
uintptr(unsafe.Pointer(&areDevToolsEnabled)),
)
if err != windows.ERROR_SUCCESS {
return false, err
}
return areDevToolsEnabled, nil
}
func (i *ICoreWebViewSettings) PutAreDevToolsEnabled(areDevToolsEnabled bool) error {
var err error
_, _, err = i.vtbl.PutAreDevToolsEnabled.Call(
uintptr(unsafe.Pointer(i)),
uintptr(boolToInt(areDevToolsEnabled)),
)
if err != windows.ERROR_SUCCESS {
return err
}
return nil
}
func (i *ICoreWebViewSettings) GetAreDefaultContextMenusEnabled() (bool, error) {
var err error
var enabled bool
_, _, err = i.vtbl.GetAreDefaultContextMenusEnabled.Call(
uintptr(unsafe.Pointer(i)),
uintptr(unsafe.Pointer(&enabled)),
)
if err != windows.ERROR_SUCCESS {
return false, err
}
return enabled, nil
}
func (i *ICoreWebViewSettings) PutAreDefaultContextMenusEnabled(enabled bool) error {
var err error
_, _, err = i.vtbl.PutAreDefaultContextMenusEnabled.Call(
uintptr(unsafe.Pointer(i)),
uintptr(boolToInt(enabled)),
)
if err != windows.ERROR_SUCCESS {
return err
}
return nil
}
func (i *ICoreWebViewSettings) GetAreHostObjectsAllowed() (bool, error) {
var err error
var allowed bool
_, _, err = i.vtbl.GetAreHostObjectsAllowed.Call(
uintptr(unsafe.Pointer(i)),
uintptr(unsafe.Pointer(&allowed)),
)
if err != windows.ERROR_SUCCESS {
return false, err
}
return allowed, nil
}
func (i *ICoreWebViewSettings) PutAreHostObjectsAllowed(allowed bool) error {
var err error
_, _, err = i.vtbl.PutAreHostObjectsAllowed.Call(
uintptr(unsafe.Pointer(i)),
uintptr(boolToInt(allowed)),
)
if err != windows.ERROR_SUCCESS {
return err
}
return nil
}
func (i *ICoreWebViewSettings) GetIsZoomControlEnabled() (bool, error) {
var err error
var enabled bool
_, _, err = i.vtbl.GetIsZoomControlEnabled.Call(
uintptr(unsafe.Pointer(i)),
uintptr(unsafe.Pointer(&enabled)),
)
if err != windows.ERROR_SUCCESS {
return false, err
}
return enabled, nil
}
func (i *ICoreWebViewSettings) PutIsZoomControlEnabled(enabled bool) error {
var err error
_, _, err = i.vtbl.PutIsZoomControlEnabled.Call(
uintptr(unsafe.Pointer(i)),
uintptr(boolToInt(enabled)),
)
if err != windows.ERROR_SUCCESS {
return err
}
return nil
}
func (i *ICoreWebViewSettings) GetIsBuiltInErrorPageEnabled() (bool, error) {
var err error
var enabled bool
_, _, err = i.vtbl.GetIsBuiltInErrorPageEnabled.Call(
uintptr(unsafe.Pointer(i)),
uintptr(unsafe.Pointer(&enabled)),
)
if err != windows.ERROR_SUCCESS {
return false, err
}
return enabled, nil
}
func (i *ICoreWebViewSettings) PutIsBuiltInErrorPageEnabled(enabled bool) error {
var err error
_, _, err = i.vtbl.PutIsBuiltInErrorPageEnabled.Call(
uintptr(unsafe.Pointer(i)),
uintptr(boolToInt(enabled)),
)
if err != windows.ERROR_SUCCESS {
return err
}
return nil
}
func (i *ICoreWebViewSettings) GetUserAgent() (string, error) {
var err error
// Create *uint16 to hold result
var _userAgent *uint16
_, _, err = i.vtbl.GetUserAgent.Call(
uintptr(unsafe.Pointer(i)),
uintptr(unsafe.Pointer(_userAgent)),
)
if err != windows.ERROR_SUCCESS {
return "", err
} // Get result and cleanup
userAgent := windows.UTF16PtrToString(_userAgent)
windows.CoTaskMemFree(unsafe.Pointer(_userAgent))
return userAgent, nil
}
func (i *ICoreWebViewSettings) PutUserAgent(userAgent string) error {
var err error
// Convert string 'userAgent' to *uint16
_userAgent, err := windows.UTF16PtrFromString(userAgent)
if err != nil {
return err
}
_, _, err = i.vtbl.PutUserAgent.Call(
uintptr(unsafe.Pointer(i)),
uintptr(unsafe.Pointer(_userAgent)),
)
if err != windows.ERROR_SUCCESS {
return err
}
return nil
}
func (i *ICoreWebViewSettings) GetAreBrowserAcceleratorKeysEnabled() (bool, error) {
var err error
var enabled bool
_, _, err = i.vtbl.GetAreBrowserAcceleratorKeysEnabled.Call(
uintptr(unsafe.Pointer(i)),
uintptr(unsafe.Pointer(&enabled)),
)
if err != windows.ERROR_SUCCESS {
return false, err
}
return enabled, nil
}
func (i *ICoreWebViewSettings) PutAreBrowserAcceleratorKeysEnabled(enabled bool) error {
var err error
_, _, err = i.vtbl.PutAreBrowserAcceleratorKeysEnabled.Call(
uintptr(unsafe.Pointer(i)),
uintptr(boolToInt(enabled)),
)
if err != windows.ERROR_SUCCESS {
return err
}
return nil
}
func (i *ICoreWebViewSettings) GetIsPinchZoomEnabled() (bool, error) {
var err error
var enabled bool
_, _, err = i.vtbl.GetIsPinchZoomEnabled.Call(
uintptr(unsafe.Pointer(i)),
uintptr(unsafe.Pointer(&enabled)),
)
if err != windows.ERROR_SUCCESS {
return false, err
}
return enabled, nil
}
func (i *ICoreWebViewSettings) PutIsPinchZoomEnabled(enabled bool) error {
var err error
_, _, err = i.vtbl.PutIsPinchZoomEnabled.Call(
uintptr(unsafe.Pointer(i)),
uintptr(boolToInt(enabled)),
)
if err != windows.ERROR_SUCCESS {
return err
}
return nil
}
func (i *ICoreWebViewSettings) GetIsSwipeNavigationEnabled() (bool, error) {
var err error
var enabled bool
_, _, err = i.vtbl.GetIsSwipeNavigationEnabled.Call(
uintptr(unsafe.Pointer(i)),
uintptr(unsafe.Pointer(&enabled)),
)
if err != windows.ERROR_SUCCESS {
return false, err
}
return enabled, nil
}
func (i *ICoreWebViewSettings) PutIsSwipeNavigationEnabled(enabled bool) error {
var err error
_, _, err = i.vtbl.PutIsSwipeNavigationEnabled.Call(
uintptr(unsafe.Pointer(i)),
uintptr(boolToInt(enabled)),
)
if err != windows.ERROR_SUCCESS {
return err
}
return nil
}

View File

@ -1,54 +0,0 @@
//go:build windows
package edge
import (
"io"
"syscall"
"unsafe"
"golang.org/x/sys/windows"
)
type _IStreamVtbl struct {
_IUnknownVtbl
Read ComProc
Write ComProc
}
type IStream struct {
vtbl *_IStreamVtbl
}
func (i *IStream) Release() error {
return i.vtbl.CallRelease(unsafe.Pointer(i))
}
func (i *IStream) Read(p []byte) (int, error) {
bufLen := len(p)
if bufLen == 0 {
return 0, nil
}
var n int
res, _, err := i.vtbl.Read.Call(
uintptr(unsafe.Pointer(i)),
uintptr(unsafe.Pointer(&p[0])),
uintptr(bufLen),
uintptr(unsafe.Pointer(&n)),
)
if err != windows.ERROR_SUCCESS {
return 0, err
}
switch windows.Handle(res) {
case windows.S_OK:
// The buffer has been completely filled
return n, nil
case windows.S_FALSE:
// The buffer has been filled with less than len data and the stream is EOF
return n, io.EOF
default:
return 0, syscall.Errno(res)
}
}

View File

@ -1,419 +0,0 @@
//go:build windows
// +build windows
package edge
import (
"errors"
"log"
"os"
"path/filepath"
"strings"
"sync/atomic"
"syscall"
"unsafe"
"github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/go-webview2/internal/w32"
"golang.org/x/sys/windows"
)
type Rect = w32.Rect
type Chromium struct {
hwnd uintptr
controller *ICoreWebView2Controller
webview *ICoreWebView2
inited uintptr
envCompleted *iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandler
controllerCompleted *iCoreWebView2CreateCoreWebView2ControllerCompletedHandler
webMessageReceived *iCoreWebView2WebMessageReceivedEventHandler
permissionRequested *iCoreWebView2PermissionRequestedEventHandler
webResourceRequested *iCoreWebView2WebResourceRequestedEventHandler
acceleratorKeyPressed *ICoreWebView2AcceleratorKeyPressedEventHandler
navigationCompleted *ICoreWebView2NavigationCompletedEventHandler
processFailed *ICoreWebView2ProcessFailedEventHandler
environment *ICoreWebView2Environment
padding Rect
// Settings
Debug bool
DataPath string
BrowserPath string
AdditionalBrowserArgs []string
// permissions
permissions map[CoreWebView2PermissionKind]CoreWebView2PermissionState
globalPermission *CoreWebView2PermissionState
// Callbacks
MessageCallback func(string)
WebResourceRequestedCallback func(request *ICoreWebView2WebResourceRequest, args *ICoreWebView2WebResourceRequestedEventArgs)
NavigationCompletedCallback func(sender *ICoreWebView2, args *ICoreWebView2NavigationCompletedEventArgs)
ProcessFailedCallback func(sender *ICoreWebView2, args *ICoreWebView2ProcessFailedEventArgs)
AcceleratorKeyCallback func(uint) bool
}
func NewChromium() *Chromium {
e := &Chromium{}
/*
All these handlers are passed to native code through syscalls with 'uintptr(unsafe.Pointer(handler))' and we know
that a pointer to those will be kept in the native code. Furthermore these handlers als contain pointer to other Go
structs like the vtable.
This violates the unsafe.Pointer rule '(4) Conversion of a Pointer to a uintptr when calling syscall.Syscall.' because
theres no guarantee that Go doesn't move these objects.
AFAIK currently the Go runtime doesn't move HEAP objects, so we should be safe with these handlers. But they don't
guarantee it, because in the future Go might use a compacting GC.
There's a proposal to add a runtime.Pin function, to prevent moving pinned objects, which would allow to easily fix
this issue by just pinning the handlers. The https://go-review.googlesource.com/c/go/+/367296/ should land in Go 1.19.
*/
e.envCompleted = newICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler(e)
e.controllerCompleted = newICoreWebView2CreateCoreWebView2ControllerCompletedHandler(e)
e.webMessageReceived = newICoreWebView2WebMessageReceivedEventHandler(e)
e.permissionRequested = newICoreWebView2PermissionRequestedEventHandler(e)
e.webResourceRequested = newICoreWebView2WebResourceRequestedEventHandler(e)
e.acceleratorKeyPressed = newICoreWebView2AcceleratorKeyPressedEventHandler(e)
e.navigationCompleted = newICoreWebView2NavigationCompletedEventHandler(e)
e.processFailed = newICoreWebView2ProcessFailedEventHandler(e)
e.permissions = make(map[CoreWebView2PermissionKind]CoreWebView2PermissionState)
return e
}
func (e *Chromium) Embed(hwnd uintptr) bool {
e.hwnd = hwnd
dataPath := e.DataPath
if dataPath == "" {
currentExePath := make([]uint16, windows.MAX_PATH)
_, err := windows.GetModuleFileName(windows.Handle(0), &currentExePath[0], windows.MAX_PATH)
if err != nil {
// What to do here?
return false
}
currentExeName := filepath.Base(windows.UTF16ToString(currentExePath))
dataPath = filepath.Join(os.Getenv("AppData"), currentExeName)
}
if e.BrowserPath != "" {
if _, err := os.Stat(e.BrowserPath); errors.Is(err, os.ErrNotExist) {
log.Printf("Browser path %s does not exist", e.BrowserPath)
return false
}
}
browserArgs := strings.Join(e.AdditionalBrowserArgs, " ")
if err := createCoreWebView2EnvironmentWithOptions(e.BrowserPath, dataPath, e.envCompleted, browserArgs); err != nil {
log.Printf("Error calling Webview2Loader: %v", err)
return false
}
var msg w32.Msg
for {
if atomic.LoadUintptr(&e.inited) != 0 {
break
}
r, _, _ := w32.User32GetMessageW.Call(
uintptr(unsafe.Pointer(&msg)),
0,
0,
0,
)
if r == 0 {
break
}
w32.User32TranslateMessage.Call(uintptr(unsafe.Pointer(&msg)))
w32.User32DispatchMessageW.Call(uintptr(unsafe.Pointer(&msg)))
}
e.Init("window.external={invoke:s=>window.chrome.webview.postMessage(s)}")
return true
}
func (e *Chromium) SetPadding(padding Rect) {
if e.padding.Top == padding.Top && e.padding.Bottom == padding.Bottom &&
e.padding.Left == padding.Left && e.padding.Right == padding.Right {
return
}
e.padding = padding
e.Resize()
}
func (e *Chromium) Resize() {
if e.hwnd == 0 {
return
}
var bounds w32.Rect
w32.User32GetClientRect.Call(e.hwnd, uintptr(unsafe.Pointer(&bounds)))
bounds.Top += e.padding.Top
bounds.Bottom -= e.padding.Bottom
bounds.Left += e.padding.Left
bounds.Right -= e.padding.Right
e.SetSize(bounds)
}
func (e *Chromium) Navigate(url string) {
e.webview.vtbl.Navigate.Call(
uintptr(unsafe.Pointer(e.webview)),
uintptr(unsafe.Pointer(windows.StringToUTF16Ptr(url))),
)
}
func (e *Chromium) Init(script string) {
e.webview.vtbl.AddScriptToExecuteOnDocumentCreated.Call(
uintptr(unsafe.Pointer(e.webview)),
uintptr(unsafe.Pointer(windows.StringToUTF16Ptr(script))),
0,
)
}
func (e *Chromium) Eval(script string) {
_script, err := windows.UTF16PtrFromString(script)
if err != nil {
log.Fatal(err)
}
e.webview.vtbl.ExecuteScript.Call(
uintptr(unsafe.Pointer(e.webview)),
uintptr(unsafe.Pointer(_script)),
0,
)
}
func (e *Chromium) Show() error {
return e.controller.PutIsVisible(true)
}
func (e *Chromium) Hide() error {
return e.controller.PutIsVisible(false)
}
func (e *Chromium) QueryInterface(_, _ uintptr) uintptr {
return 0
}
func (e *Chromium) AddRef() uintptr {
return 1
}
func (e *Chromium) Release() uintptr {
return 1
}
func (e *Chromium) EnvironmentCompleted(res uintptr, env *ICoreWebView2Environment) uintptr {
if int32(res) < 0 {
log.Fatalf("Creating environment failed with %08x: %s", res, syscall.Errno(res))
}
env.vtbl.AddRef.Call(uintptr(unsafe.Pointer(env)))
e.environment = env
env.vtbl.CreateCoreWebView2Controller.Call(
uintptr(unsafe.Pointer(env)),
e.hwnd,
uintptr(unsafe.Pointer(e.controllerCompleted)),
)
return 0
}
func (e *Chromium) CreateCoreWebView2ControllerCompleted(res uintptr, controller *ICoreWebView2Controller) uintptr {
if int32(res) < 0 {
log.Fatalf("Creating controller failed with %08x: %s", res, syscall.Errno(res))
}
controller.vtbl.AddRef.Call(uintptr(unsafe.Pointer(controller)))
e.controller = controller
var token _EventRegistrationToken
controller.vtbl.GetCoreWebView2.Call(
uintptr(unsafe.Pointer(controller)),
uintptr(unsafe.Pointer(&e.webview)),
)
e.webview.vtbl.AddRef.Call(
uintptr(unsafe.Pointer(e.webview)),
)
e.webview.vtbl.AddWebMessageReceived.Call(
uintptr(unsafe.Pointer(e.webview)),
uintptr(unsafe.Pointer(e.webMessageReceived)),
uintptr(unsafe.Pointer(&token)),
)
e.webview.vtbl.AddPermissionRequested.Call(
uintptr(unsafe.Pointer(e.webview)),
uintptr(unsafe.Pointer(e.permissionRequested)),
uintptr(unsafe.Pointer(&token)),
)
e.webview.vtbl.AddWebResourceRequested.Call(
uintptr(unsafe.Pointer(e.webview)),
uintptr(unsafe.Pointer(e.webResourceRequested)),
uintptr(unsafe.Pointer(&token)),
)
e.webview.vtbl.AddNavigationCompleted.Call(
uintptr(unsafe.Pointer(e.webview)),
uintptr(unsafe.Pointer(e.navigationCompleted)),
uintptr(unsafe.Pointer(&token)),
)
e.webview.vtbl.AddProcessFailed.Call(
uintptr(unsafe.Pointer(e.webview)),
uintptr(unsafe.Pointer(e.processFailed)),
uintptr(unsafe.Pointer(&token)),
)
e.controller.AddAcceleratorKeyPressed(e.acceleratorKeyPressed, &token)
atomic.StoreUintptr(&e.inited, 1)
return 0
}
func (e *Chromium) MessageReceived(sender *ICoreWebView2, args *iCoreWebView2WebMessageReceivedEventArgs) uintptr {
var message *uint16
args.vtbl.TryGetWebMessageAsString.Call(
uintptr(unsafe.Pointer(args)),
uintptr(unsafe.Pointer(&message)),
)
if e.MessageCallback != nil {
e.MessageCallback(w32.Utf16PtrToString(message))
}
sender.vtbl.PostWebMessageAsString.Call(
uintptr(unsafe.Pointer(sender)),
uintptr(unsafe.Pointer(message)),
)
windows.CoTaskMemFree(unsafe.Pointer(message))
return 0
}
func (e *Chromium) SetPermission(kind CoreWebView2PermissionKind, state CoreWebView2PermissionState) {
e.permissions[kind] = state
}
func (e *Chromium) SetGlobalPermission(state CoreWebView2PermissionState) {
e.globalPermission = &state
}
func (e *Chromium) PermissionRequested(_ *ICoreWebView2, args *iCoreWebView2PermissionRequestedEventArgs) uintptr {
var kind CoreWebView2PermissionKind
args.vtbl.GetPermissionKind.Call(
uintptr(unsafe.Pointer(args)),
uintptr(kind),
)
var result CoreWebView2PermissionState
if e.globalPermission != nil {
result = *e.globalPermission
} else {
var ok bool
result, ok = e.permissions[kind]
if !ok {
result = CoreWebView2PermissionStateDefault
}
}
args.vtbl.PutState.Call(
uintptr(unsafe.Pointer(args)),
uintptr(result),
)
return 0
}
func (e *Chromium) WebResourceRequested(sender *ICoreWebView2, args *ICoreWebView2WebResourceRequestedEventArgs) uintptr {
req, err := args.GetRequest()
if err != nil {
log.Fatal(err)
}
defer req.Release()
if e.WebResourceRequestedCallback != nil {
e.WebResourceRequestedCallback(req, args)
}
return 0
}
func (e *Chromium) AddWebResourceRequestedFilter(filter string, ctx COREWEBVIEW2_WEB_RESOURCE_CONTEXT) {
err := e.webview.AddWebResourceRequestedFilter(filter, ctx)
if err != nil {
log.Fatal(err)
}
}
func (e *Chromium) Environment() *ICoreWebView2Environment {
return e.environment
}
// AcceleratorKeyPressed is called when an accelerator key is pressed.
// If the AcceleratorKeyCallback method has been set, it will defer handling of the keypress
// to the callback. That callback returns a bool indicating if the event was handled.
func (e *Chromium) AcceleratorKeyPressed(sender *ICoreWebView2Controller, args *ICoreWebView2AcceleratorKeyPressedEventArgs) uintptr {
if e.AcceleratorKeyCallback == nil {
return 0
}
eventKind, _ := args.GetKeyEventKind()
if eventKind == COREWEBVIEW2_KEY_EVENT_KIND_KEY_DOWN ||
eventKind == COREWEBVIEW2_KEY_EVENT_KIND_SYSTEM_KEY_DOWN {
virtualKey, _ := args.GetVirtualKey()
status, _ := args.GetPhysicalKeyStatus()
if !status.WasKeyDown {
args.PutHandled(e.AcceleratorKeyCallback(virtualKey))
return 0
}
}
args.PutHandled(false)
return 0
}
func (e *Chromium) GetSettings() (*ICoreWebViewSettings, error) {
return e.webview.GetSettings()
}
func (e *Chromium) GetController() *ICoreWebView2Controller {
return e.controller
}
func boolToInt(input bool) int {
if input {
return 1
}
return 0
}
func (e *Chromium) NavigationCompleted(sender *ICoreWebView2, args *ICoreWebView2NavigationCompletedEventArgs) uintptr {
if e.NavigationCompletedCallback != nil {
e.NavigationCompletedCallback(sender, args)
}
return 0
}
func (e *Chromium) ProcessFailed(sender *ICoreWebView2, args *ICoreWebView2ProcessFailedEventArgs) uintptr {
if e.ProcessFailedCallback != nil {
e.ProcessFailedCallback(sender, args)
}
return 0
}
func (e *Chromium) NotifyParentWindowPositionChanged() error {
//It looks like the wndproc function is called before the controller initialization is complete.
//Because of this the controller is nil
if e.controller == nil {
return nil
}
return e.controller.NotifyParentWindowPositionChanged()
}
func (e *Chromium) Focus() {
err := e.controller.MoveFocus(COREWEBVIEW2_MOVE_FOCUS_REASON_PROGRAMMATIC)
if err != nil {
log.Fatal(err)
}
}
func (e *Chromium) PutZoomFactor(zoomFactor float64) {
err := e.controller.PutZoomFactor(zoomFactor)
if err != nil {
log.Fatal(err)
}
}
func (e *Chromium) OpenDevToolsWindow() {
e.webview.OpenDevToolsWindow()
}

View File

@ -1,23 +0,0 @@
//go:build windows
// +build windows
package edge
import (
"github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/go-webview2/internal/w32"
"unsafe"
)
func (e *Chromium) SetSize(bounds w32.Rect) {
if e.controller == nil {
return
}
e.controller.vtbl.PutBounds.Call(
uintptr(unsafe.Pointer(e.controller)),
uintptr(bounds.Left),
uintptr(bounds.Top),
uintptr(bounds.Right),
uintptr(bounds.Bottom),
)
}

View File

@ -1,20 +0,0 @@
//go:build windows
// +build windows
package edge
import (
"github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/go-webview2/internal/w32"
"unsafe"
)
func (e *Chromium) SetSize(bounds w32.Rect) {
if e.controller == nil {
return
}
e.controller.vtbl.PutBounds.Call(
uintptr(unsafe.Pointer(e.controller)),
uintptr(unsafe.Pointer(&bounds)),
)
}

View File

@ -1,23 +0,0 @@
//go:build windows
// +build windows
package edge
import (
"unsafe"
"github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/go-webview2/internal/w32"
)
func (e *Chromium) SetSize(bounds w32.Rect) {
if e.controller == nil {
return
}
words := (*[2]uintptr)(unsafe.Pointer(&bounds))
e.controller.vtbl.PutBounds.Call(
uintptr(unsafe.Pointer(e.controller)),
words[0],
words[1],
)
}

View File

@ -1,503 +0,0 @@
//go:build windows
// +build windows
package edge
import (
"fmt"
"log"
"runtime"
"syscall"
"unsafe"
"github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/go-webview2/internal/w32"
"golang.org/x/sys/windows"
)
func init() {
runtime.LockOSThread()
r, _, _ := w32.Ole32CoInitializeEx.Call(0, 2)
if int(r) < 0 {
log.Printf("Warning: CoInitializeEx call failed: E=%08x", r)
}
}
type _EventRegistrationToken struct {
value int64
}
type CoreWebView2PermissionKind uint32
const (
CoreWebView2PermissionKindUnknownPermission CoreWebView2PermissionKind = iota
CoreWebView2PermissionKindMicrophone
CoreWebView2PermissionKindCamera
CoreWebView2PermissionKindGeolocation
CoreWebView2PermissionKindNotifications
CoreWebView2PermissionKindOtherSensors
CoreWebView2PermissionKindClipboardRead
)
type CoreWebView2PermissionState uint32
const (
CoreWebView2PermissionStateDefault CoreWebView2PermissionState = iota
CoreWebView2PermissionStateAllow
CoreWebView2PermissionStateDeny
)
// ComProc stores a COM procedure.
type ComProc uintptr
// NewComProc creates a new COM proc from a Go function.
func NewComProc(fn interface{}) ComProc {
return ComProc(windows.NewCallback(fn))
}
// Call calls a COM procedure.
//
//go:uintptrescapes
func (p ComProc) Call(a ...uintptr) (r1, r2 uintptr, lastErr error) {
// The magic uintptrescapes comment is needed to prevent moving uintptr(unsafe.Pointer(p)) so calls to .Call() also
// satisfy the unsafe.Pointer rule "(4) Conversion of a Pointer to a uintptr when calling syscall.Syscall."
// Otherwise it might be that pointers get moved, especially pointer onto the Go stack which might grow dynamically.
// See https://pkg.go.dev/unsafe#Pointer and https://github.com/golang/go/issues/34474
switch len(a) {
case 0:
return syscall.Syscall(uintptr(p), 0, 0, 0, 0)
case 1:
return syscall.Syscall(uintptr(p), 1, a[0], 0, 0)
case 2:
return syscall.Syscall(uintptr(p), 2, a[0], a[1], 0)
case 3:
return syscall.Syscall(uintptr(p), 3, a[0], a[1], a[2])
case 4:
return syscall.Syscall6(uintptr(p), 4, a[0], a[1], a[2], a[3], 0, 0)
case 5:
return syscall.Syscall6(uintptr(p), 5, a[0], a[1], a[2], a[3], a[4], 0)
case 6:
return syscall.Syscall6(uintptr(p), 6, a[0], a[1], a[2], a[3], a[4], a[5])
case 7:
return syscall.Syscall9(uintptr(p), 7, a[0], a[1], a[2], a[3], a[4], a[5], a[6], 0, 0)
case 8:
return syscall.Syscall9(uintptr(p), 8, a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], 0)
case 9:
return syscall.Syscall9(uintptr(p), 9, a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8])
case 10:
return syscall.Syscall12(uintptr(p), 10, a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], 0, 0)
case 11:
return syscall.Syscall12(uintptr(p), 11, a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], 0)
case 12:
return syscall.Syscall12(uintptr(p), 12, a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11])
case 13:
return syscall.Syscall15(uintptr(p), 13, a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], 0, 0)
case 14:
return syscall.Syscall15(uintptr(p), 14, a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13], 0)
case 15:
return syscall.Syscall15(uintptr(p), 15, a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13], a[14])
default:
panic("too many arguments")
}
}
// IUnknown
type _IUnknownVtbl struct {
QueryInterface ComProc
AddRef ComProc
Release ComProc
}
func (i *_IUnknownVtbl) CallRelease(this unsafe.Pointer) error {
_, _, err := i.Release.Call(
uintptr(this),
)
if err != windows.ERROR_SUCCESS {
return err
}
return nil
}
type _IUnknownImpl interface {
QueryInterface(refiid, object uintptr) uintptr
AddRef() uintptr
Release() uintptr
}
// ICoreWebView2
type iCoreWebView2Vtbl struct {
_IUnknownVtbl
GetSettings ComProc
GetSource ComProc
Navigate ComProc
NavigateToString ComProc
AddNavigationStarting ComProc
RemoveNavigationStarting ComProc
AddContentLoading ComProc
RemoveContentLoading ComProc
AddSourceChanged ComProc
RemoveSourceChanged ComProc
AddHistoryChanged ComProc
RemoveHistoryChanged ComProc
AddNavigationCompleted ComProc
RemoveNavigationCompleted ComProc
AddFrameNavigationStarting ComProc
RemoveFrameNavigationStarting ComProc
AddFrameNavigationCompleted ComProc
RemoveFrameNavigationCompleted ComProc
AddScriptDialogOpening ComProc
RemoveScriptDialogOpening ComProc
AddPermissionRequested ComProc
RemovePermissionRequested ComProc
AddProcessFailed ComProc
RemoveProcessFailed ComProc
AddScriptToExecuteOnDocumentCreated ComProc
RemoveScriptToExecuteOnDocumentCreated ComProc
ExecuteScript ComProc
CapturePreview ComProc
Reload ComProc
PostWebMessageAsJSON ComProc
PostWebMessageAsString ComProc
AddWebMessageReceived ComProc
RemoveWebMessageReceived ComProc
CallDevToolsProtocolMethod ComProc
GetBrowserProcessID ComProc
GetCanGoBack ComProc
GetCanGoForward ComProc
GoBack ComProc
GoForward ComProc
GetDevToolsProtocolEventReceiver ComProc
Stop ComProc
AddNewWindowRequested ComProc
RemoveNewWindowRequested ComProc
AddDocumentTitleChanged ComProc
RemoveDocumentTitleChanged ComProc
GetDocumentTitle ComProc
AddHostObjectToScript ComProc
RemoveHostObjectFromScript ComProc
OpenDevToolsWindow ComProc
AddContainsFullScreenElementChanged ComProc
RemoveContainsFullScreenElementChanged ComProc
GetContainsFullScreenElement ComProc
AddWebResourceRequested ComProc
RemoveWebResourceRequested ComProc
AddWebResourceRequestedFilter ComProc
RemoveWebResourceRequestedFilter ComProc
AddWindowCloseRequested ComProc
RemoveWindowCloseRequested ComProc
}
type ICoreWebView2 struct {
vtbl *iCoreWebView2Vtbl
}
func (i *ICoreWebView2) GetSettings() (*ICoreWebViewSettings, error) {
var err error
var settings *ICoreWebViewSettings
_, _, err = i.vtbl.GetSettings.Call(
uintptr(unsafe.Pointer(i)),
uintptr(unsafe.Pointer(&settings)),
)
if err != windows.ERROR_SUCCESS {
return nil, err
}
return settings, nil
}
// ICoreWebView2Environment
type iCoreWebView2EnvironmentVtbl struct {
_IUnknownVtbl
CreateCoreWebView2Controller ComProc
CreateWebResourceResponse ComProc
GetBrowserVersionString ComProc
AddNewBrowserVersionAvailable ComProc
RemoveNewBrowserVersionAvailable ComProc
}
type ICoreWebView2Environment struct {
vtbl *iCoreWebView2EnvironmentVtbl
}
// CreateWebResourceResponse creates a new ICoreWebView2WebResourceResponse, it must be released after finishing using it.
func (e *ICoreWebView2Environment) CreateWebResourceResponse(content []byte, statusCode int, reasonPhrase string, headers string) (*ICoreWebView2WebResourceResponse, error) {
var err error
var stream uintptr
if len(content) > 0 {
// Create stream for response
stream, err = w32.SHCreateMemStream(content)
if err != nil {
return nil, err
}
// Release the IStream after we are finished, CreateWebResourceResponse Call will increase the reference
// count on IStream and therefore it won't be freed until the reference count of the response is 0.
defer (*IStream)(unsafe.Pointer(stream)).Release()
}
// Convert string 'uri' to *uint16
_reason, err := windows.UTF16PtrFromString(reasonPhrase)
if err != nil {
return nil, err
}
// Convert string 'uri' to *uint16
_headers, err := windows.UTF16PtrFromString(headers)
if err != nil {
return nil, err
}
var response *ICoreWebView2WebResourceResponse
hr, _, err := e.vtbl.CreateWebResourceResponse.Call(
uintptr(unsafe.Pointer(e)),
stream,
uintptr(statusCode),
uintptr(unsafe.Pointer(_reason)),
uintptr(unsafe.Pointer(_headers)),
uintptr(unsafe.Pointer(&response)),
)
if windows.Handle(hr) != windows.S_OK {
return nil, syscall.Errno(hr)
}
if response == nil {
if err == nil {
err = fmt.Errorf("unknown error")
}
return nil, err
}
return response, nil
}
// ICoreWebView2WebMessageReceivedEventArgs
type iCoreWebView2WebMessageReceivedEventArgsVtbl struct {
_IUnknownVtbl
GetSource ComProc
GetWebMessageAsJSON ComProc
TryGetWebMessageAsString ComProc
}
type iCoreWebView2WebMessageReceivedEventArgs struct {
vtbl *iCoreWebView2WebMessageReceivedEventArgsVtbl
}
// ICoreWebView2PermissionRequestedEventArgs
type iCoreWebView2PermissionRequestedEventArgsVtbl struct {
_IUnknownVtbl
GetURI ComProc
GetPermissionKind ComProc
GetIsUserInitiated ComProc
GetState ComProc
PutState ComProc
GetDeferral ComProc
}
type iCoreWebView2PermissionRequestedEventArgs struct {
vtbl *iCoreWebView2PermissionRequestedEventArgsVtbl
}
// ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler
type iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandlerImpl interface {
_IUnknownImpl
EnvironmentCompleted(res uintptr, env *ICoreWebView2Environment) uintptr
}
type iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandlerVtbl struct {
_IUnknownVtbl
Invoke ComProc
}
type iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandler struct {
vtbl *iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandlerVtbl
impl iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandlerImpl
}
func _ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandlerIUnknownQueryInterface(this *iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandler, refiid, object uintptr) uintptr {
return this.impl.QueryInterface(refiid, object)
}
func _ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandlerIUnknownAddRef(this *iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandler) uintptr {
return this.impl.AddRef()
}
func _ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandlerIUnknownRelease(this *iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandler) uintptr {
return this.impl.Release()
}
func _ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandlerInvoke(this *iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandler, res uintptr, env *ICoreWebView2Environment) uintptr {
return this.impl.EnvironmentCompleted(res, env)
}
var iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandlerFn = iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandlerVtbl{
_IUnknownVtbl{
NewComProc(_ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandlerIUnknownQueryInterface),
NewComProc(_ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandlerIUnknownAddRef),
NewComProc(_ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandlerIUnknownRelease),
},
NewComProc(_ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandlerInvoke),
}
func newICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler(impl iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandlerImpl) *iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandler {
return &iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandler{
vtbl: &iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandlerFn,
impl: impl,
}
}
// ICoreWebView2WebMessageReceivedEventHandler
type iCoreWebView2WebMessageReceivedEventHandlerImpl interface {
_IUnknownImpl
MessageReceived(sender *ICoreWebView2, args *iCoreWebView2WebMessageReceivedEventArgs) uintptr
}
type iCoreWebView2WebMessageReceivedEventHandlerVtbl struct {
_IUnknownVtbl
Invoke ComProc
}
type iCoreWebView2WebMessageReceivedEventHandler struct {
vtbl *iCoreWebView2WebMessageReceivedEventHandlerVtbl
impl iCoreWebView2WebMessageReceivedEventHandlerImpl
}
func _ICoreWebView2WebMessageReceivedEventHandlerIUnknownQueryInterface(this *iCoreWebView2WebMessageReceivedEventHandler, refiid, object uintptr) uintptr {
return this.impl.QueryInterface(refiid, object)
}
func _ICoreWebView2WebMessageReceivedEventHandlerIUnknownAddRef(this *iCoreWebView2WebMessageReceivedEventHandler) uintptr {
return this.impl.AddRef()
}
func _ICoreWebView2WebMessageReceivedEventHandlerIUnknownRelease(this *iCoreWebView2WebMessageReceivedEventHandler) uintptr {
return this.impl.Release()
}
func _ICoreWebView2WebMessageReceivedEventHandlerInvoke(this *iCoreWebView2WebMessageReceivedEventHandler, sender *ICoreWebView2, args *iCoreWebView2WebMessageReceivedEventArgs) uintptr {
return this.impl.MessageReceived(sender, args)
}
var iCoreWebView2WebMessageReceivedEventHandlerFn = iCoreWebView2WebMessageReceivedEventHandlerVtbl{
_IUnknownVtbl{
NewComProc(_ICoreWebView2WebMessageReceivedEventHandlerIUnknownQueryInterface),
NewComProc(_ICoreWebView2WebMessageReceivedEventHandlerIUnknownAddRef),
NewComProc(_ICoreWebView2WebMessageReceivedEventHandlerIUnknownRelease),
},
NewComProc(_ICoreWebView2WebMessageReceivedEventHandlerInvoke),
}
func newICoreWebView2WebMessageReceivedEventHandler(impl iCoreWebView2WebMessageReceivedEventHandlerImpl) *iCoreWebView2WebMessageReceivedEventHandler {
return &iCoreWebView2WebMessageReceivedEventHandler{
vtbl: &iCoreWebView2WebMessageReceivedEventHandlerFn,
impl: impl,
}
}
// ICoreWebView2PermissionRequestedEventHandler
type iCoreWebView2PermissionRequestedEventHandlerImpl interface {
_IUnknownImpl
PermissionRequested(sender *ICoreWebView2, args *iCoreWebView2PermissionRequestedEventArgs) uintptr
}
type iCoreWebView2PermissionRequestedEventHandlerVtbl struct {
_IUnknownVtbl
Invoke ComProc
}
type iCoreWebView2PermissionRequestedEventHandler struct {
vtbl *iCoreWebView2PermissionRequestedEventHandlerVtbl
impl iCoreWebView2PermissionRequestedEventHandlerImpl
}
func _ICoreWebView2PermissionRequestedEventHandlerIUnknownQueryInterface(this *iCoreWebView2PermissionRequestedEventHandler, refiid, object uintptr) uintptr {
return this.impl.QueryInterface(refiid, object)
}
func _ICoreWebView2PermissionRequestedEventHandlerIUnknownAddRef(this *iCoreWebView2PermissionRequestedEventHandler) uintptr {
return this.impl.AddRef()
}
func _ICoreWebView2PermissionRequestedEventHandlerIUnknownRelease(this *iCoreWebView2PermissionRequestedEventHandler) uintptr {
return this.impl.Release()
}
func _ICoreWebView2PermissionRequestedEventHandlerInvoke(this *iCoreWebView2PermissionRequestedEventHandler, sender *ICoreWebView2, args *iCoreWebView2PermissionRequestedEventArgs) uintptr {
return this.impl.PermissionRequested(sender, args)
}
var iCoreWebView2PermissionRequestedEventHandlerFn = iCoreWebView2PermissionRequestedEventHandlerVtbl{
_IUnknownVtbl{
NewComProc(_ICoreWebView2PermissionRequestedEventHandlerIUnknownQueryInterface),
NewComProc(_ICoreWebView2PermissionRequestedEventHandlerIUnknownAddRef),
NewComProc(_ICoreWebView2PermissionRequestedEventHandlerIUnknownRelease),
},
NewComProc(_ICoreWebView2PermissionRequestedEventHandlerInvoke),
}
func newICoreWebView2PermissionRequestedEventHandler(impl iCoreWebView2PermissionRequestedEventHandlerImpl) *iCoreWebView2PermissionRequestedEventHandler {
return &iCoreWebView2PermissionRequestedEventHandler{
vtbl: &iCoreWebView2PermissionRequestedEventHandlerFn,
impl: impl,
}
}
func (i *ICoreWebView2) AddWebResourceRequestedFilter(uri string, resourceContext COREWEBVIEW2_WEB_RESOURCE_CONTEXT) error {
var err error
// Convert string 'uri' to *uint16
_uri, err := windows.UTF16PtrFromString(uri)
if err != nil {
return err
}
_, _, err = i.vtbl.AddWebResourceRequestedFilter.Call(
uintptr(unsafe.Pointer(i)),
uintptr(unsafe.Pointer(_uri)),
uintptr(resourceContext),
)
if err != windows.ERROR_SUCCESS {
return err
}
return nil
}
func (i *ICoreWebView2) AddNavigationCompleted(eventHandler *ICoreWebView2NavigationCompletedEventHandler, token *_EventRegistrationToken) error {
var err error
_, _, err = i.vtbl.AddNavigationCompleted.Call(
uintptr(unsafe.Pointer(i)),
uintptr(unsafe.Pointer(eventHandler)),
uintptr(unsafe.Pointer(&token)),
)
if err != windows.ERROR_SUCCESS {
return err
}
return nil
}
func (i *ICoreWebView2) AddProcessFailed(eventHandler *ICoreWebView2ProcessFailedEventHandler, token *_EventRegistrationToken) error {
var err error
_, _, err = i.vtbl.AddProcessFailed.Call(
uintptr(unsafe.Pointer(i)),
uintptr(unsafe.Pointer(eventHandler)),
uintptr(unsafe.Pointer(&token)),
)
if err != windows.ERROR_SUCCESS {
return err
}
return nil
}
func (i *ICoreWebView2) OpenDevToolsWindow() error {
var err error
_, _, err = i.vtbl.OpenDevToolsWindow.Call(
uintptr(unsafe.Pointer(i)),
)
if err != windows.ERROR_SUCCESS {
return err
}
return nil
}

View File

@ -1,29 +0,0 @@
//go:build windows && !native_webview2loader
package edge
import (
"unsafe"
"github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/go-webview2/webviewloader"
)
func createCoreWebView2EnvironmentWithOptions(browserExecutableFolder, userDataFolder string, environmentCompletedHandle *iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandler, additionalBrowserArgs string) error {
e := &environmentCreatedHandler{environmentCompletedHandle}
return webviewloader.CreateCoreWebView2EnvironmentWithOptions(
e,
webviewloader.WithBrowserExecutableFolder(browserExecutableFolder),
webviewloader.WithUserDataFolder(userDataFolder),
webviewloader.WithAdditionalBrowserArguments(additionalBrowserArgs),
)
}
type environmentCreatedHandler struct {
originalHandler *iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandler
}
func (r *environmentCreatedHandler) EnvironmentCompleted(errorCode webviewloader.HRESULT, createdEnvironment *webviewloader.ICoreWebView2Environment) webviewloader.HRESULT {
env := (*ICoreWebView2Environment)(unsafe.Pointer(createdEnvironment))
res := r.originalHandler.impl.EnvironmentCompleted(uintptr(errorCode), env)
return webviewloader.HRESULT(res)
}

View File

@ -1,41 +0,0 @@
//go:build windows && native_webview2loader
package edge
import (
"fmt"
"syscall"
"unsafe"
"github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/go-webview2/webviewloader"
"golang.org/x/sys/windows"
)
func createCoreWebView2EnvironmentWithOptions(browserExecutableFolder, userDataFolder string, environmentCompletedHandle *iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandler, additionalBrowserArgs string) error {
browserPathPtr, err := windows.UTF16PtrFromString(browserExecutableFolder)
if err != nil {
return fmt.Errorf("Error calling UTF16PtrFromString for %s: %v", browserExecutableFolder, err)
}
userPathPtr, err := windows.UTF16PtrFromString(userDataFolder)
if err != nil {
return fmt.Errorf("Error calling UTF16PtrFromString for %s: %v", userDataFolder, err)
}
hr, err := webviewloader.CreateCoreWebView2EnvironmentWithOptions(
browserPathPtr,
userPathPtr,
uintptr(unsafe.Pointer(environmentCompletedHandle)),
additionalBrowserArgs,
)
if hr != 0 {
if err == nil || err == windows.ERROR_SUCCESS {
err = syscall.Errno(hr)
}
return err
}
return nil
}

View File

@ -1,225 +0,0 @@
//go:build windows
package edge
// This code has been adapted from: https://github.com/go-ole/go-ole
/*
The MIT License (MIT)
Copyright © 2013-2017 Yasuhiro Matsumoto, <mattn.jp@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the Software), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
const hextable = "0123456789ABCDEF"
const emptyGUID = "{00000000-0000-0000-0000-000000000000}"
// GUID is Windows API specific GUID type.
//
// This exists to match Windows GUID type for direct passing for COM.
// Format is in xxxxxxxx-xxxx-xxxx-xxxxxxxxxxxxxxxx.
type GUID struct {
Data1 uint32
Data2 uint16
Data3 uint16
Data4 [8]byte
}
// NewGUID converts the given string into a globally unique identifier that is
// compliant with the Windows API.
//
// The supplied string may be in any of these formats:
//
// XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
// XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
// {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}
//
// The conversion of the supplied string is not case-sensitive.
func NewGUID(guid string) *GUID {
d := []byte(guid)
var d1, d2, d3, d4a, d4b []byte
switch len(d) {
case 38:
if d[0] != '{' || d[37] != '}' {
return nil
}
d = d[1:37]
fallthrough
case 36:
if d[8] != '-' || d[13] != '-' || d[18] != '-' || d[23] != '-' {
return nil
}
d1 = d[0:8]
d2 = d[9:13]
d3 = d[14:18]
d4a = d[19:23]
d4b = d[24:36]
case 32:
d1 = d[0:8]
d2 = d[8:12]
d3 = d[12:16]
d4a = d[16:20]
d4b = d[20:32]
default:
return nil
}
var g GUID
var ok1, ok2, ok3, ok4 bool
g.Data1, ok1 = decodeHexUint32(d1)
g.Data2, ok2 = decodeHexUint16(d2)
g.Data3, ok3 = decodeHexUint16(d3)
g.Data4, ok4 = decodeHexByte64(d4a, d4b)
if ok1 && ok2 && ok3 && ok4 {
return &g
}
return nil
}
func decodeHexUint32(src []byte) (value uint32, ok bool) {
var b1, b2, b3, b4 byte
var ok1, ok2, ok3, ok4 bool
b1, ok1 = decodeHexByte(src[0], src[1])
b2, ok2 = decodeHexByte(src[2], src[3])
b3, ok3 = decodeHexByte(src[4], src[5])
b4, ok4 = decodeHexByte(src[6], src[7])
value = (uint32(b1) << 24) | (uint32(b2) << 16) | (uint32(b3) << 8) | uint32(b4)
ok = ok1 && ok2 && ok3 && ok4
return
}
func decodeHexUint16(src []byte) (value uint16, ok bool) {
var b1, b2 byte
var ok1, ok2 bool
b1, ok1 = decodeHexByte(src[0], src[1])
b2, ok2 = decodeHexByte(src[2], src[3])
value = (uint16(b1) << 8) | uint16(b2)
ok = ok1 && ok2
return
}
func decodeHexByte64(s1 []byte, s2 []byte) (value [8]byte, ok bool) {
var ok1, ok2, ok3, ok4, ok5, ok6, ok7, ok8 bool
value[0], ok1 = decodeHexByte(s1[0], s1[1])
value[1], ok2 = decodeHexByte(s1[2], s1[3])
value[2], ok3 = decodeHexByte(s2[0], s2[1])
value[3], ok4 = decodeHexByte(s2[2], s2[3])
value[4], ok5 = decodeHexByte(s2[4], s2[5])
value[5], ok6 = decodeHexByte(s2[6], s2[7])
value[6], ok7 = decodeHexByte(s2[8], s2[9])
value[7], ok8 = decodeHexByte(s2[10], s2[11])
ok = ok1 && ok2 && ok3 && ok4 && ok5 && ok6 && ok7 && ok8
return
}
func decodeHexByte(c1, c2 byte) (value byte, ok bool) {
var n1, n2 byte
var ok1, ok2 bool
n1, ok1 = decodeHexChar(c1)
n2, ok2 = decodeHexChar(c2)
value = (n1 << 4) | n2
ok = ok1 && ok2
return
}
func decodeHexChar(c byte) (byte, bool) {
switch {
case '0' <= c && c <= '9':
return c - '0', true
case 'a' <= c && c <= 'f':
return c - 'a' + 10, true
case 'A' <= c && c <= 'F':
return c - 'A' + 10, true
}
return 0, false
}
// String converts the GUID to string form. It will adhere to this pattern:
//
// {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}
//
// If the GUID is nil, the string representation of an empty GUID is returned:
//
// {00000000-0000-0000-0000-000000000000}
func (guid *GUID) String() string {
if guid == nil {
return emptyGUID
}
var c [38]byte
c[0] = '{'
putUint32Hex(c[1:9], guid.Data1)
c[9] = '-'
putUint16Hex(c[10:14], guid.Data2)
c[14] = '-'
putUint16Hex(c[15:19], guid.Data3)
c[19] = '-'
putByteHex(c[20:24], guid.Data4[0:2])
c[24] = '-'
putByteHex(c[25:37], guid.Data4[2:8])
c[37] = '}'
return string(c[:])
}
func putUint32Hex(b []byte, v uint32) {
b[0] = hextable[byte(v>>24)>>4]
b[1] = hextable[byte(v>>24)&0x0f]
b[2] = hextable[byte(v>>16)>>4]
b[3] = hextable[byte(v>>16)&0x0f]
b[4] = hextable[byte(v>>8)>>4]
b[5] = hextable[byte(v>>8)&0x0f]
b[6] = hextable[byte(v)>>4]
b[7] = hextable[byte(v)&0x0f]
}
func putUint16Hex(b []byte, v uint16) {
b[0] = hextable[byte(v>>8)>>4]
b[1] = hextable[byte(v>>8)&0x0f]
b[2] = hextable[byte(v)>>4]
b[3] = hextable[byte(v)&0x0f]
}
func putByteHex(dst, src []byte) {
for i := 0; i < len(src); i++ {
dst[i*2] = hextable[src[i]>>4]
dst[i*2+1] = hextable[src[i]&0x0f]
}
}
// IsEqualGUID compares two GUID.
//
// Not constant time comparison.
func IsEqualGUID(guid1 *GUID, guid2 *GUID) bool {
return guid1.Data1 == guid2.Data1 &&
guid1.Data2 == guid2.Data2 &&
guid1.Data3 == guid2.Data3 &&
guid1.Data4[0] == guid2.Data4[0] &&
guid1.Data4[1] == guid2.Data4[1] &&
guid1.Data4[2] == guid2.Data4[2] &&
guid1.Data4[3] == guid2.Data4[3] &&
guid1.Data4[4] == guid2.Data4[4] &&
guid1.Data4[5] == guid2.Data4[5] &&
guid1.Data4[6] == guid2.Data4[6] &&
guid1.Data4[7] == guid2.Data4[7]
}

View File

@ -1,16 +0,0 @@
ISC License (ISC)
Copyright (c) 2020 John Chadwick
Copyright (c) 2022 Wails Project Developers
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.

View File

@ -1,19 +0,0 @@
# Webviewloader
Webviewloader is a port of [OpenWebView2Loader](https://github.com/jchv/OpenWebView2Loader) to Go.
It is intended to be feature-complete with the original WebView2Loader distributed with
the WebView2 NuGet package, but some features are intentionally not implemented.
## Status
- [x] CompareBrowserVersions
- [x] CreateCoreWebView2Environment
- [x] CreateCoreWebView2EnvironmentWithOptions
- [x] GetAvailableCoreWebView2BrowserVersionString
## Not implemented features
- Registry Overrides of Parameters
- Env Variable Overrides of Parameters
- Does not incorporate `GetCurrentPackageInfo` to search for an installed runtime

View File

@ -1,177 +0,0 @@
//go:build windows && !native_webview2loader
package webviewloader
import (
"fmt"
"os"
"path/filepath"
"syscall"
"unsafe"
"github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/go-webview2/pkg/combridge"
"golang.org/x/sys/windows"
)
func init() {
// TODO: Set a flag here and output this message only if the flag is set in the application startup
fmt.Println("DEB | Using go webview2loader")
preventEnvAndRegistryOverrides()
}
type webView2RunTimeType int32
const (
webView2RunTimeTypeInstalled webView2RunTimeType = 0x00
webView2RunTimeTypeRedistributable webView2RunTimeType = 0x01
)
// CreateCoreWebView2Environment creates an evergreen WebView2 Environment using the installed WebView2 Runtime version.
//
// This is equivalent to running CreateCoreWebView2EnvironmentWithOptions without any options.
// For more information, see CreateCoreWebView2EnvironmentWithOptions.
func CreateCoreWebView2Environment(environmentCompletedHandler ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler) error {
return CreateCoreWebView2EnvironmentWithOptions(environmentCompletedHandler)
}
// CreateCoreWebView2EnvironmentWithOptions creates an environment with a custom version of WebView2 Runtime,
// user data folder, and with or without additional options.
//
// See https://docs.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/webview2-idl?#createcorewebview2environmentwithoptions
func CreateCoreWebView2EnvironmentWithOptions(environmentCompletedHandler ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler, opts ...option) error {
var params environmentOptions
for _, opt := range opts {
opt(&params)
}
var err error
var dllPath string
var runtimeType webView2RunTimeType
if browserExecutableFolder := params.browserExecutableFolder; browserExecutableFolder != "" {
runtimeType = webView2RunTimeTypeRedistributable
dllPath, err = findEmbeddedClientDll(browserExecutableFolder)
} else {
runtimeType = webView2RunTimeTypeInstalled
dllPath, _, err = findInstalledClientDll(params.preferCanary)
}
if err != nil {
return err
}
return createWebViewEnvironmentWithClientDll(dllPath, runtimeType, params.userDataFolder,
&params, environmentCompletedHandler)
}
func createWebViewEnvironmentWithClientDll(lpLibFileName string, runtimeType webView2RunTimeType, userDataFolder string,
envOptions *environmentOptions, envCompletedHandler ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler) error {
if !filepath.IsAbs(lpLibFileName) {
return fmt.Errorf("lpLibFileName must be absolute")
}
dll, err := windows.LoadDLL(lpLibFileName)
if err != nil {
return fmt.Errorf("Loading DLL failed: %w", err)
}
defer func() {
canUnloadProc, err := dll.FindProc("DllCanUnloadNow")
if err != nil {
return
}
if r1, _, _ := canUnloadProc.Call(); r1 != windows.NO_ERROR {
return
}
dll.Release()
}()
createProc, err := dll.FindProc("CreateWebViewEnvironmentWithOptionsInternal")
if err != nil {
return fmt.Errorf("Unable to find CreateWebViewEnvironmentWithOptionsInternal entrypoint: %w", err)
}
userDataPtr, err := windows.UTF16PtrFromString(userDataFolder)
if err != nil {
return err
}
envOptionsCom := combridge.New2[iCoreWebView2EnvironmentOptions, iCoreWebView2EnvironmentOptions2](
envOptions, envOptions)
defer envOptionsCom.Close()
envCompletedHandler = &environmentCreatedHandler{envCompletedHandler}
envCompletedCom := combridge.New[iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandler](envCompletedHandler)
defer envCompletedCom.Close()
preventEnvAndRegistryOverrides()
const unknown = 1
hr, _, err := createProc.Call(
uintptr(unknown),
uintptr(runtimeType),
uintptr(unsafe.Pointer(userDataPtr)),
uintptr(envOptionsCom.Ref()),
uintptr(envCompletedCom.Ref()))
if hr != 0 {
if err == nil || err == windows.ERROR_SUCCESS {
err = syscall.Errno(hr)
}
return err
}
return nil
}
type environmentCreatedHandler struct {
originalHandler ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler
}
func (r *environmentCreatedHandler) EnvironmentCompleted(errorCode HRESULT, createdEnvironment *ICoreWebView2Environment) HRESULT {
// The OpenWebview2Loader has some retry logic and retries once, didn't encounter any case when this would have been
// needed during the development: https://github.com/jchv/OpenWebView2Loader/blob/master/Source/WebView2Loader.cpp#L202
if createdEnvironment != nil {
// May or may not be necessary, but the official WebView2Loader seems to do it.
iidICoreWebView2Environment := windows.GUID{
Data1: 0xb96d755e,
Data2: 0x0319,
Data3: 0x4e92,
Data4: [8]byte{0xa2, 0x96, 0x23, 0x43, 0x6f, 0x46, 0xa1, 0xfc},
}
if err := createdEnvironment.QueryInterface(&iidICoreWebView2Environment, &createdEnvironment); err != nil {
createdEnvironment = nil
errNo, ok := err.(syscall.Errno)
if !ok {
errNo = syscall.Errno(windows.E_FAIL)
}
errorCode = HRESULT(errNo)
}
}
r.originalHandler.EnvironmentCompleted(errorCode, createdEnvironment)
if createdEnvironment != nil {
createdEnvironment.Release()
}
return HRESULT(windows.S_OK)
}
func preventEnvAndRegistryOverrides() {
// Setting these env variables to empty string also prevents registry overrides because webview2
// checks for existence and not for empty value
os.Setenv("WEBVIEW2_PIPE_FOR_SCRIPT_DEBUGGER", "")
os.Setenv("WEBVIEW2_ADDITIONAL_BROWSER_ARGUMENTS", "")
os.Setenv("WEBVIEW2_RELEASE_CHANNEL_PREFERENCE", "0")
// The following seems not be be required because those are only used by the webview2loader which
// in this case is implemented on our own. But nevertheless set them to empty to be consistent.
os.Setenv("WEBVIEW2_BROWSER_EXECUTABLE_FOLDER", "")
os.Setenv("WEBVIEW2_USER_DATA_FOLDER", "")
}

View File

@ -1,42 +0,0 @@
//go:build windows && !native_webview2loader
package webviewloader
import (
"github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/go-webview2/pkg/combridge"
)
// HRESULT
//
// See https://docs.microsoft.com/en-us/windows/win32/seccrypto/common-hresult-values
type HRESULT int32
// ICoreWebView2Environment Represents the WebView2 Environment
//
// See https://docs.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/icorewebview2environment
type ICoreWebView2Environment = combridge.IUnknownImpl
// ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler receives the WebView2Environment created using CreateCoreWebView2Environment.
type ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler interface {
// EnvironmentCompleted is invoked to receive the created WebView2Environment
//
// See https://docs.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/icorewebview2createcorewebview2environmentcompletedhandler?#invoke
EnvironmentCompleted(errorCode HRESULT, createdEnvironment *ICoreWebView2Environment) HRESULT
}
type iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandler interface {
combridge.IUnknown
ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler
}
func init() {
combridge.RegisterVTable[combridge.IUnknown, iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandler](
"{4e8a3389-c9d8-4bd2-b6b5-124fee6cc14d}",
_iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandlerInvoke,
)
}
func _iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandlerInvoke(this uintptr, errorCode HRESULT, env *combridge.IUnknownImpl) uintptr {
res := combridge.Resolve[iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandler](this).EnvironmentCompleted(errorCode, env)
return uintptr(res)
}

View File

@ -1,276 +0,0 @@
//go:build windows && !native_webview2loader
package webviewloader
import (
"unicode/utf16"
"unsafe"
"github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/go-webview2/pkg/combridge"
"golang.org/x/sys/windows"
)
// WithBrowserExecutableFolder to specify whether WebView2 controls use a fixed or installed version
// of the WebView2 Runtime that exists on a user machine.
//
// To use a fixed version of the WebView2 Runtime,
// pass the folder path that contains the fixed version of the WebView2 Runtime.
// BrowserExecutableFolder supports both relative (to the application's executable) and absolute files paths.
// To create WebView2 controls that use the installed version of the WebView2 Runtime that exists on user
// machines, pass a empty string to WithBrowserExecutableFolder. In this scenario, the API tries to find a
// compatible version of the WebView2 Runtime that is installed on the user machine (first at the machine level,
// and then per user) using the selected channel preference. The path of fixed version of the WebView2 Runtime
// should not contain \Edge\Application\. When such a path is used, the API fails with HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED).
func WithBrowserExecutableFolder(folder string) option {
return func(wvep *environmentOptions) {
wvep.browserExecutableFolder = folder
}
}
// WithUserDataFolder specifies to user data folder location for WebView2
//
// You may specify the userDataFolder to change the default user data folder location for WebView2.
// The path is either an absolute file path or a relative file path that is interpreted as relative
// to the compiled code for the current process.
// Dhe default user data ({Executable File Name}.WebView2) folder is created in the same directory
// next to the compiled code for the app. WebView2 creation fails if the compiled code is running
// in a directory in which the process does not have permission to create a new directory.
// The app is responsible to clean up the associated user data folder when it is done.
func WithUserDataFolder(folder string) option {
return func(wvep *environmentOptions) {
wvep.userDataFolder = folder
}
}
// WithAdditionalBrowserArguments changes the behavior of the WebView.
//
// The arguments are passed to the
// browser process as part of the command. For more information about
// using command-line switches with Chromium browser processes, navigate to
// [Run Chromium with Flags][ChromiumDevelopersHowTosRunWithFlags].
// The value appended to a switch is appended to the browser process, for
// example, in `--edge-webview-switches=xxx` the value is `xxx`. If you
// specify a switch that is important to WebView functionality, it is
// ignored, for example, `--user-data-dir`. Specific features are disabled
// internally and blocked from being enabled. If a switch is specified
// multiple times, only the last instance is used.
//
// \> [!NOTE]\n\> A merge of the different values of the same switch is not attempted,
// except for disabled and enabled features. The features specified by
// `--enable-features` and `--disable-features` are merged with simple
// logic.\n\> * The features is the union of the specified features
// and built-in features. If a feature is disabled, it is removed from the
// enabled features list.
//
// If you specify command-line switches and use the
// `additionalBrowserArguments` parameter, the `--edge-webview-switches`
// value takes precedence and is processed last. If a switch fails to
// parse, the switch is ignored. The default state for the operation is
// to run the browser process with no extra flags.
//
// [ChromiumDevelopersHowTosRunWithFlags]: https://www.chromium.org/developers/how-tos/run-chromium-with-flags "Run Chromium with flags | The Chromium Projects"
func WithAdditionalBrowserArguments(args string) option {
return func(wvep *environmentOptions) {
wvep.additionalBrowserArguments = args
}
}
// WithLanguage sets the default display language for WebView.
//
// It applies to browser UI such as
// context menu and dialogs. It also applies to the `accept-languages` HTTP
// header that WebView sends to websites. It is in the format of
//
// `language[-country]` where `language` is the 2-letter code from
// [ISO 639][ISO639LanguageCodesHtml]
// and `country` is the
// 2-letter code from
// [ISO 3166][ISOStandard72482Html].
//
// [ISO639LanguageCodesHtml]: https://www.iso.org/iso-639-language-codes.html "ISO 639 | ISO"
// [ISOStandard72482Html]: https://www.iso.org/standard/72482.html "ISO 3166-1:2020 | ISO"
func WithLanguage(lang string) option {
return func(wvep *environmentOptions) {
wvep.language = lang
}
}
// WithTargetCompatibleBrowserVersion secifies the version of the WebView2 Runtime binaries required to be
// compatible with your app.
//
// This defaults to the WebView2 Runtime version
// that corresponds with the version of the SDK the app is using. The
// format of this value is the same as the format of the
// `BrowserVersionString` property and other `BrowserVersion` values. Only
// the version part of the `BrowserVersion` value is respected. The channel
// suffix, if it exists, is ignored. The version of the WebView2 Runtime
// binaries actually used may be different from the specified
// `TargetCompatibleBrowserVersion`. The binaries are only guaranteed to be
// compatible. Verify the actual version on the `BrowserVersionString`
// property on the `ICoreWebView2Environment`.
func WithTargetCompatibleBrowserVersion(version string) option {
return func(wvep *environmentOptions) {
wvep.targetCompatibleBrowserVersion = version
}
}
// WithAllowSingleSignOnUsingOSPrimaryAccount is used to enable
// single sign on with Azure Active Directory (AAD) and personal Microsoft
// Account (MSA) resources inside WebView. All AAD accounts, connected to
// Windows and shared for all apps, are supported. For MSA, SSO is only enabled
// for the account associated for Windows account login, if any.
// Default is disabled. Universal Windows Platform apps must also declare
// `enterpriseCloudSSO`
// [Restricted capabilities][WindowsUwpPackagingAppCapabilityDeclarationsRestrictedCapabilities]
// for the single sign on (SSO) to work.
//
// [WindowsUwpPackagingAppCapabilityDeclarationsRestrictedCapabilities]: /windows/uwp/packaging/app-capability-declarations\#restricted-capabilities "Restricted capabilities - App capability declarations | Microsoft Docs"
func WithAllowSingleSignOnUsingOSPrimaryAccount(allow bool) option {
return func(wvep *environmentOptions) {
wvep.allowSingleSignOnUsingOSPrimaryAccount = allow
}
}
// WithExclusiveUserDataFolderAccess specifies that the WebView environment
// obtains exclusive access to the user data folder.
//
// If the user data folder is already being used by another WebView environment with a
// different value for `ExclusiveUserDataFolderAccess` property, the creation of a WebView2Controller
// using the environment object will fail with `HRESULT_FROM_WIN32(ERROR_INVALID_STATE)`.
// When set as TRUE, no other WebView can be created from other processes using WebView2Environment
// objects with the same UserDataFolder. This prevents other processes from creating WebViews
// which share the same browser process instance, since sharing is performed among
// WebViews that have the same UserDataFolder. When another process tries to create a
// WebView2Controller from an WebView2Environment object created with the same user data folder,
// it will fail with `HRESULT_FROM_WIN32(ERROR_INVALID_STATE)`.
func WithExclusiveUserDataFolderAccess(exclusive bool) option {
return func(wvep *environmentOptions) {
wvep.exclusiveUserDataFolderAccess = exclusive
}
}
type option func(*environmentOptions)
var _ iCoreWebView2EnvironmentOptions = &environmentOptions{}
var _ iCoreWebView2EnvironmentOptions2 = &environmentOptions{}
type environmentOptions struct {
browserExecutableFolder string
userDataFolder string
preferCanary bool
additionalBrowserArguments string
language string
targetCompatibleBrowserVersion string
allowSingleSignOnUsingOSPrimaryAccount bool
exclusiveUserDataFolderAccess bool
}
func (o *environmentOptions) AdditionalBrowserArguments() string {
return o.additionalBrowserArguments
}
func (o *environmentOptions) Language() string {
return o.language
}
func (o *environmentOptions) TargetCompatibleBrowserVersion() string {
v := o.targetCompatibleBrowserVersion
if v == "" {
v = kMinimumCompatibleVersion
}
return v
}
func (o *environmentOptions) AllowSingleSignOnUsingOSPrimaryAccount() bool {
return o.allowSingleSignOnUsingOSPrimaryAccount
}
func (o *environmentOptions) ExclusiveUserDataFolderAccess() bool {
return o.exclusiveUserDataFolderAccess
}
type iCoreWebView2EnvironmentOptions interface {
combridge.IUnknown
AdditionalBrowserArguments() string
Language() string
TargetCompatibleBrowserVersion() string
AllowSingleSignOnUsingOSPrimaryAccount() bool
}
type iCoreWebView2EnvironmentOptions2 interface {
combridge.IUnknown
ExclusiveUserDataFolderAccess() bool
}
func init() {
combridge.RegisterVTable[combridge.IUnknown, iCoreWebView2EnvironmentOptions](
"{2fde08a8-1e9a-4766-8c05-95a9ceb9d1c5}",
_iCoreWebView2EnvironmentOptionsAdditionalBrowserArguments,
_iCoreWebView2EnvironmentOptionsNOP,
_iCoreWebView2EnvironmentOptionsLanguage,
_iCoreWebView2EnvironmentOptionsNOP,
_iCoreWebView2EnvironmentTargetCompatibleBrowserVersion,
_iCoreWebView2EnvironmentOptionsNOP,
_iCoreWebView2EnvironmentOptionsAllowSingleSignOnUsingOSPrimaryAccount,
_iCoreWebView2EnvironmentOptionsNOP,
)
combridge.RegisterVTable[combridge.IUnknown, iCoreWebView2EnvironmentOptions2](
"{ff85c98a-1ba7-4a6b-90c8-2b752c89e9e2}",
_iCoreWebView2EnvironmentOptions2ExclusiveUserDataFolderAccess,
_iCoreWebView2EnvironmentOptionsNOP,
)
}
func _iCoreWebView2EnvironmentOptionsNOP(this uintptr) uintptr {
return uintptr(windows.S_FALSE)
}
func _iCoreWebView2EnvironmentOptionsAdditionalBrowserArguments(this uintptr, value **uint16) uintptr {
v := combridge.Resolve[iCoreWebView2EnvironmentOptions](this).AdditionalBrowserArguments()
*value = stringToOleString(v)
return uintptr(windows.S_OK)
}
func _iCoreWebView2EnvironmentOptionsLanguage(this uintptr, value **uint16) uintptr {
args := combridge.Resolve[iCoreWebView2EnvironmentOptions](this).Language()
*value = stringToOleString(args)
return uintptr(windows.S_OK)
}
func _iCoreWebView2EnvironmentTargetCompatibleBrowserVersion(this uintptr, value **uint16) uintptr {
args := combridge.Resolve[iCoreWebView2EnvironmentOptions](this).TargetCompatibleBrowserVersion()
*value = stringToOleString(args)
return uintptr(windows.S_OK)
}
func _iCoreWebView2EnvironmentOptionsAllowSingleSignOnUsingOSPrimaryAccount(this uintptr, value *int32) uintptr {
v := combridge.Resolve[iCoreWebView2EnvironmentOptions](this).AllowSingleSignOnUsingOSPrimaryAccount()
*value = boolToInt(v)
return uintptr(windows.S_OK)
}
func _iCoreWebView2EnvironmentOptions2ExclusiveUserDataFolderAccess(this uintptr, value *int32) uintptr {
v := combridge.Resolve[iCoreWebView2EnvironmentOptions2](this).ExclusiveUserDataFolderAccess()
*value = boolToInt(v)
return uintptr(windows.S_OK)
}
func stringToOleString(v string) *uint16 {
wstr := utf16.Encode([]rune(v + "\x00"))
lwstr := len(wstr)
ptr := (*uint16)(coTaskMemAlloc(2 * lwstr))
copy(unsafe.Slice(ptr, lwstr), wstr)
return ptr
}
func boolToInt(v bool) int32 {
if v {
return 1
}
return 0
}

View File

@ -1,74 +0,0 @@
//go:build windows
package webviewloader
import (
"errors"
"fmt"
"os"
"path/filepath"
"runtime"
"golang.org/x/sys/windows/registry"
)
var (
errNoClientDLLFound = errors.New("no webview2 found")
)
func findEmbeddedBrowserVersion(filename string) (string, error) {
block, err := getFileVersionInfo(filename)
if err != nil {
return "", err
}
info, err := verQueryValueString(block, "\\StringFileInfo\\040904B0\\ProductVersion")
if err != nil {
return "", err
}
return info, nil
}
func findEmbeddedClientDll(embeddedEdgeSubFolder string) (outClientPath string, err error) {
if !filepath.IsAbs(embeddedEdgeSubFolder) {
exe, err := os.Executable()
if err != nil {
return "", err
}
embeddedEdgeSubFolder = filepath.Join(filepath.Dir(exe), embeddedEdgeSubFolder)
}
return findClientDllInFolder(embeddedEdgeSubFolder)
}
func findClientDllInFolder(folder string) (string, error) {
arch := ""
switch runtime.GOARCH {
case "arm64":
arch = "arm64"
case "amd64":
arch = "x64"
case "386":
arch = "x86"
default:
return "", fmt.Errorf("Unsupported architecture")
}
dllPath := filepath.Join(folder, "EBWebView", arch, "EmbeddedBrowserWebView.dll")
if _, err := os.Stat(dllPath); err != nil {
return "", mapFindErr(err)
}
return dllPath, nil
}
func mapFindErr(err error) error {
if errors.Is(err, registry.ErrNotExist) {
return errNoClientDLLFound
}
if errors.Is(err, os.ErrNotExist) {
return errNoClientDLLFound
}
return err
}

View File

@ -1,94 +0,0 @@
//go:build windows && !native_webview2loader
package webviewloader
import (
"path/filepath"
"golang.org/x/sys/windows/registry"
)
const (
kNumChannels = 4
kInstallKeyPath = "Software\\Microsoft\\EdgeUpdate\\ClientState\\"
kMinimumCompatibleVersion = "86.0.616.0"
)
var (
kChannelName = [kNumChannels]string{
"", "beta", "dev", "canary", // "internal"
}
kChannelUuid = [kNumChannels]string{
"{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}",
"{2CD8A007-E189-409D-A2C8-9AF4EF3C72AA}",
"{0D50BFEC-CD6A-4F9A-964C-C7416E3ACB10}",
"{65C35B14-6C1D-4122-AC46-7148CC9D6497}",
//"{BE59E8FD-089A-411B-A3B0-051D9E417818}",
}
minimumCompatibleVersion, _ = parseVersion(kMinimumCompatibleVersion)
)
func findInstalledClientDll(preferCanary bool) (clientPath string, version *version, err error) {
for i := 0; i < kNumChannels; i++ {
channel := i
if preferCanary {
channel = (kNumChannels - 1) - i
}
key := kInstallKeyPath + kChannelUuid[channel]
for _, checkSystem := range []bool{true, false} {
clientPath, version, err := findInstalledClientDllForChannel(key, checkSystem)
if err == errNoClientDLLFound {
continue
}
if err != nil {
return "", nil, err
}
version.channel = kChannelName[channel]
return clientPath, version, nil
}
}
return "", nil, errNoClientDLLFound
}
func findInstalledClientDllForChannel(subKey string, system bool) (clientPath string, clientVersion *version, err error) {
key := registry.LOCAL_MACHINE
if !system {
key = registry.CURRENT_USER
}
regKey, err := registry.OpenKey(key, subKey, registry.READ|registry.WOW64_32KEY)
if err != nil {
return "", nil, mapFindErr(err)
}
defer regKey.Close()
embeddedEdgeSubFolder, _, err := regKey.GetStringValue("EBWebView")
if err != nil {
return "", nil, mapFindErr(err)
}
if embeddedEdgeSubFolder == "" {
return "", nil, errNoClientDLLFound
}
versionString := filepath.Base(embeddedEdgeSubFolder)
version, err := parseVersion(versionString)
if err != nil {
return "", nil, errNoClientDLLFound
}
if version.compare(minimumCompatibleVersion) < 0 {
return "", nil, errNoClientDLLFound
}
dllPath, err := findEmbeddedClientDll(embeddedEdgeSubFolder)
if err != nil {
return "", nil, mapFindErr(err)
}
return dllPath, &version, nil
}

View File

@ -1,173 +0,0 @@
//go:build windows && native_webview2loader
package webviewloader
import (
"errors"
"fmt"
"os"
"sync"
"unsafe"
"github.com/jchv/go-winloader"
"golang.org/x/sys/windows"
)
func init() {
preventEnvAndRegistryOverrides(nil, nil, "")
}
var (
memOnce sync.Once
memModule winloader.Module
memCreate winloader.Proc
memCompareBrowserVersions winloader.Proc
memGetAvailableCoreWebView2BrowserVersionString winloader.Proc
memErr error
)
const (
// https://referencesource.microsoft.com/#system.web/Util/hresults.cs,20
E_FILENOTFOUND = 0x80070002
)
// CompareBrowserVersions will compare the 2 given versions and return:
//
// Less than zero: v1 < v2
// zero: v1 == v2
// Greater than zero: v1 > v2
func CompareBrowserVersions(v1 string, v2 string) (int, error) {
_v1, err := windows.UTF16PtrFromString(v1)
if err != nil {
return 0, err
}
_v2, err := windows.UTF16PtrFromString(v2)
if err != nil {
return 0, err
}
err = loadFromMemory()
if err != nil {
return 0, err
}
var result int32
_, _, err = memCompareBrowserVersions.Call(
uint64(uintptr(unsafe.Pointer(_v1))),
uint64(uintptr(unsafe.Pointer(_v2))),
uint64(uintptr(unsafe.Pointer(&result))))
if err != windows.ERROR_SUCCESS {
return 0, err
}
return int(result), nil
}
// GetAvailableCoreWebView2BrowserVersionString returns version of the webview2 runtime.
// If path is empty, it will try to find installed webview2 is the system.
// If there is no version installed, a blank string is returned.
func GetAvailableCoreWebView2BrowserVersionString(path string) (string, error) {
if path != "" {
// The default implementation fails if CGO and a fixed browser path is used. It's caused by the go-winloader
// which loads the native DLL from memory.
// Use the new GoWebView2Loader in this case, in the future we will make GoWebView2Loader
// feature-complete and remove the use of the native DLL and go-winloader.
version, err := goGetAvailableCoreWebView2BrowserVersionString(path)
if errors.Is(err, errNoClientDLLFound) {
// WebView2 is not found
return "", nil
} else if err != nil {
return "", err
}
return version, nil
}
err := loadFromMemory()
if err != nil {
return "", err
}
var browserPath *uint16 = nil
if path != "" {
browserPath, err = windows.UTF16PtrFromString(path)
if err != nil {
return "", fmt.Errorf("error calling UTF16PtrFromString for %s: %v", path, err)
}
}
preventEnvAndRegistryOverrides(browserPath, nil, "")
var result *uint16
res, _, err := memGetAvailableCoreWebView2BrowserVersionString.Call(
uint64(uintptr(unsafe.Pointer(browserPath))),
uint64(uintptr(unsafe.Pointer(&result))))
if res != 0 {
if res == E_FILENOTFOUND {
// WebView2 is not installed
return "", nil
}
return "", fmt.Errorf("Unable to call GetAvailableCoreWebView2BrowserVersionString (%x): %w", res, err)
}
version := windows.UTF16PtrToString(result)
windows.CoTaskMemFree(unsafe.Pointer(result))
return version, nil
}
// CreateCoreWebView2EnvironmentWithOptions tries to load WebviewLoader2 and
// call the CreateCoreWebView2EnvironmentWithOptions routine.
func CreateCoreWebView2EnvironmentWithOptions(browserExecutableFolder, userDataFolder *uint16, environmentCompletedHandle uintptr, additionalBrowserArgs string) (uintptr, error) {
err := loadFromMemory()
if err != nil {
return 0, err
}
preventEnvAndRegistryOverrides(browserExecutableFolder, userDataFolder, additionalBrowserArgs)
res, _, _ := memCreate.Call(
uint64(uintptr(unsafe.Pointer(browserExecutableFolder))),
uint64(uintptr(unsafe.Pointer(userDataFolder))),
0,
uint64(environmentCompletedHandle),
)
return uintptr(res), nil
}
func loadFromMemory() error {
var err error
// DLL is not available natively. Try loading embedded copy.
memOnce.Do(func() {
memModule, memErr = winloader.LoadFromMemory(WebView2Loader)
if memErr != nil {
err = fmt.Errorf("Unable to load WebView2Loader.dll from memory: %w", memErr)
return
}
memCreate = memModule.Proc("CreateCoreWebView2EnvironmentWithOptions")
memCompareBrowserVersions = memModule.Proc("CompareBrowserVersions")
memGetAvailableCoreWebView2BrowserVersionString = memModule.Proc("GetAvailableCoreWebView2BrowserVersionString")
})
return err
}
func preventEnvAndRegistryOverrides(browserFolder, userDataFolder *uint16, additionalBrowserArgs string) {
// Setting these env variables to empty string also prevents registry overrides because webview2loader
// checks for existence and not for empty value
os.Setenv("WEBVIEW2_PIPE_FOR_SCRIPT_DEBUGGER", "")
// Set these overrides to the values or empty to prevent registry and external env overrides
os.Setenv("WEBVIEW2_ADDITIONAL_BROWSER_ARGUMENTS", additionalBrowserArgs)
os.Setenv("WEBVIEW2_RELEASE_CHANNEL_PREFERENCE", "0")
os.Setenv("WEBVIEW2_BROWSER_EXECUTABLE_FOLDER", windows.UTF16PtrToString(browserFolder))
os.Setenv("WEBVIEW2_USER_DATA_FOLDER", windows.UTF16PtrToString(userDataFolder))
}
func goGetAvailableCoreWebView2BrowserVersionString(browserExecutableFolder string) (string, error) {
clientPath, err := findEmbeddedClientDll(browserExecutableFolder)
if err != nil {
return "", err
}
return findEmbeddedBrowserVersion(clientPath)
}

View File

@ -1,8 +0,0 @@
//go:build windows && native_webview2loader
package webviewloader
import _ "embed"
//go:embed x86/WebView2Loader.dll
var WebView2Loader []byte

View File

@ -1,8 +0,0 @@
//go:build windows && native_webview2loader
package webviewloader
import _ "embed"
//go:embed x64/WebView2Loader.dll
var WebView2Loader []byte

View File

@ -1,8 +0,0 @@
//go:build windows && native_webview2loader
package webviewloader
import _ "embed"
//go:embed arm64/WebView2Loader.dll
var WebView2Loader []byte

View File

@ -1,143 +0,0 @@
//go:build windows
package webviewloader
import (
"fmt"
"syscall"
"unicode/utf16"
"unsafe"
"golang.org/x/sys/windows"
)
var (
modkernel32 = windows.NewLazySystemDLL("kernel32.dll")
procGlobalAlloc = modkernel32.NewProc("GlobalAlloc")
procGlobalFree = modkernel32.NewProc("GlobalFree")
modversion = windows.NewLazySystemDLL("version.dll")
procGetFileVersionInfoSize = modversion.NewProc("GetFileVersionInfoSizeW")
procGetFileVersionInfo = modversion.NewProc("GetFileVersionInfoW")
procVerQueryValue = modversion.NewProc("VerQueryValueW")
modole32 = windows.NewLazySystemDLL("ole32.dll")
procCoTaskMemAlloc = modole32.NewProc("CoTaskMemAlloc")
)
func getFileVersionInfo(path string) ([]byte, error) {
lptstrFilename, err := syscall.UTF16PtrFromString(path)
if err != nil {
return nil, err
}
size, _, err := procGetFileVersionInfoSize.Call(
uintptr(unsafe.Pointer(lptstrFilename)),
0,
)
err = maskErrorSuccess(err)
if size == 0 && err == nil {
err = fmt.Errorf("GetFileVersionInfoSize failed")
}
if err != nil {
return nil, err
}
data := make([]byte, size)
ret, _, err := procGetFileVersionInfo.Call(
uintptr(unsafe.Pointer(lptstrFilename)),
0,
uintptr(size),
uintptr(unsafe.Pointer(&data[0])),
)
err = maskErrorSuccess(err)
if ret == 0 && err == nil {
err = fmt.Errorf("GetFileVersionInfo failed")
}
if err != nil {
return nil, err
}
return data, nil
}
func verQueryValueString(block []byte, subBlock string) (string, error) {
// Allocate memory from native side to make sure the block doesn't get moved
// because we get a pointer into that memory block from the native verQueryValue
// call back.
pBlock := globalAlloc(0, uint32(len(block)))
defer globalFree(unsafe.Pointer(pBlock))
// Copy the memory region into native side memory
copy(unsafe.Slice((*byte)(pBlock), len(block)), block)
lpSubBlock, err := syscall.UTF16PtrFromString(subBlock)
if err != nil {
return "", err
}
var lplpBuffer unsafe.Pointer
var puLen uint
ret, _, err := procVerQueryValue.Call(
uintptr(pBlock),
uintptr(unsafe.Pointer(lpSubBlock)),
uintptr(unsafe.Pointer(&lplpBuffer)),
uintptr(unsafe.Pointer(&puLen)),
)
err = maskErrorSuccess(err)
if ret == 0 && err == nil {
err = fmt.Errorf("VerQueryValue failed")
}
if err != nil {
return "", err
}
if puLen <= 1 {
return "", nil
}
puLen -= 1 // Remove Null-Terminator
wchar := unsafe.Slice((*uint16)(lplpBuffer), puLen)
return string(utf16.Decode(wchar)), nil
}
func globalAlloc(uFlags uint, dwBytes uint32) unsafe.Pointer {
ret, _, _ := procGlobalAlloc.Call(
uintptr(uFlags),
uintptr(dwBytes))
if ret == 0 {
panic("globalAlloc failed")
}
return unsafe.Pointer(ret)
}
func globalFree(data unsafe.Pointer) {
ret, _, _ := procGlobalFree.Call(uintptr(data))
if ret != 0 {
panic("globalFree failed")
}
}
func maskErrorSuccess(err error) error {
if err == windows.ERROR_SUCCESS {
return nil
}
return err
}
func coTaskMemAlloc(size int) unsafe.Pointer {
ret, _, _ := procCoTaskMemAlloc.Call(
uintptr(size))
if ret == 0 {
panic("coTaskMemAlloc failed")
}
return unsafe.Pointer(ret)
}

View File

@ -1,147 +0,0 @@
//go:build windows && !native_webview2loader
package webviewloader
import (
"errors"
"fmt"
"strconv"
"strings"
)
// CompareBrowserVersions will compare the 2 given versions and return:
//
// -1 = v1 < v2
// 0 = v1 == v2
// 1 = v1 > v2
func CompareBrowserVersions(v1 string, v2 string) (int, error) {
v, err := parseVersion(v1)
if err != nil {
return 0, fmt.Errorf("v1 invalid: %w", err)
}
w, err := parseVersion(v2)
if err != nil {
return 0, fmt.Errorf("v2 invalid: %w", err)
}
return v.compare(w), nil
}
// GetAvailableCoreWebView2BrowserVersionString get the browser version info including channel name
// if it is the WebView2 Runtime.
// Channel names are Beta, Dev, and Canary.
func GetAvailableCoreWebView2BrowserVersionString(browserExecutableFolder string) (string, error) {
if browserExecutableFolder != "" {
clientPath, err := findEmbeddedClientDll(browserExecutableFolder)
if errors.Is(err, errNoClientDLLFound) {
// WebView2 is not found
return "", nil
} else if err != nil {
return "", err
}
return findEmbeddedBrowserVersion(clientPath)
}
_, version, err := findInstalledClientDll(false)
if errors.Is(err, errNoClientDLLFound) {
return "", nil
} else if err != nil {
return "", err
}
return version.String(), nil
}
type version struct {
major int
minor int
patch int
build int
channel string
}
func (v version) String() string {
vv := fmt.Sprintf("%d.%d.%d.%d", v.major, v.minor, v.patch, v.build)
if v.channel != "" {
vv += " " + v.channel
}
return vv
}
func (v version) compare(o version) int {
if c := compareInt(v.major, o.major); c != 0 {
return c
}
if c := compareInt(v.minor, o.minor); c != 0 {
return c
}
if c := compareInt(v.patch, o.patch); c != 0 {
return c
}
return compareInt(v.build, o.build)
}
func parseVersion(v string) (version, error) {
var p version
// Split away channel information...
if i := strings.Index(v, " "); i > 0 {
p.channel = v[i+1:]
v = v[:i]
}
vv := strings.Split(v, ".")
if len(vv) > 4 {
return p, fmt.Errorf("too many version parts")
}
var err error
vv, p.major, err = parseInt(vv)
if err != nil {
return p, fmt.Errorf("bad major version: %w", err)
}
vv, p.minor, err = parseInt(vv)
if err != nil {
return p, fmt.Errorf("bad minor version: %w", err)
}
vv, p.patch, err = parseInt(vv)
if err != nil {
return p, fmt.Errorf("bad patch version: %w", err)
}
_, p.build, err = parseInt(vv)
if err != nil {
return p, fmt.Errorf("bad build version: %w", err)
}
return p, nil
}
func parseInt(v []string) ([]string, int, error) {
if len(v) == 0 {
return nil, 0, nil
}
p, err := strconv.ParseInt(v[0], 10, 32)
if err != nil {
return nil, 0, err
}
return v[1:], int(p), nil
}
func compareInt(v1, v2 int) int {
if v1 == v2 {
return 0
}
if v1 < v2 {
return -1
} else {
return +1
}
}

View File

@ -3,11 +3,10 @@
package windows package windows
import ( import (
"github.com/wailsapp/go-webview2/pkg/edge"
"sync" "sync"
"unsafe" "unsafe"
"github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge"
"github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/win32" "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/win32"
"github.com/wailsapp/wails/v2/internal/system/operatingsystem" "github.com/wailsapp/wails/v2/internal/system/operatingsystem"

View File

@ -3,8 +3,9 @@ package dispatcher
import ( import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"github.com/wailsapp/wails/v2/internal/frontend"
"strings" "strings"
"github.com/wailsapp/wails/v2/internal/frontend"
) )
type callMessage struct { type callMessage struct {
@ -49,7 +50,12 @@ func (d *Dispatcher) processCallMessage(message string, sender frontend.Frontend
CallbackID: payload.CallbackID, CallbackID: payload.CallbackID,
} }
if err != nil { if err != nil {
callbackMessage.Err = err.Error() // Use the error formatter if one was provided
if d.errfmt != nil {
callbackMessage.Err = d.errfmt(err)
} else {
callbackMessage.Err = err.Error()
}
} else { } else {
callbackMessage.Result = result callbackMessage.Result = result
} }
@ -66,7 +72,7 @@ func (d *Dispatcher) processCallMessage(message string, sender frontend.Frontend
// CallbackMessage defines a message that contains the result of a call // CallbackMessage defines a message that contains the result of a call
type CallbackMessage struct { type CallbackMessage struct {
Result interface{} `json:"result"` Result interface{} `json:"result"`
Err string `json:"error"` Err any `json:"error"`
CallbackID string `json:"callbackid"` CallbackID string `json:"callbackid"`
} }

View File

@ -7,6 +7,7 @@ import (
"github.com/wailsapp/wails/v2/internal/binding" "github.com/wailsapp/wails/v2/internal/binding"
"github.com/wailsapp/wails/v2/internal/frontend" "github.com/wailsapp/wails/v2/internal/frontend"
"github.com/wailsapp/wails/v2/internal/logger" "github.com/wailsapp/wails/v2/internal/logger"
"github.com/wailsapp/wails/v2/pkg/options"
) )
type Dispatcher struct { type Dispatcher struct {
@ -15,15 +16,17 @@ type Dispatcher struct {
events frontend.Events events frontend.Events
bindingsDB *binding.DB bindingsDB *binding.DB
ctx context.Context ctx context.Context
errfmt options.ErrorFormatter
} }
func NewDispatcher(ctx context.Context, log *logger.Logger, bindings *binding.Bindings, events frontend.Events) *Dispatcher { func NewDispatcher(ctx context.Context, log *logger.Logger, bindings *binding.Bindings, events frontend.Events, errfmt options.ErrorFormatter) *Dispatcher {
return &Dispatcher{ return &Dispatcher{
log: log, log: log,
bindings: bindings, bindings: bindings,
events: events, events: events,
bindingsDB: bindings.DB(), bindingsDB: bindings.DB(),
ctx: ctx, ctx: ctx,
errfmt: errfmt,
} }
} }

View File

@ -0,0 +1,50 @@
/*
--default-contextmenu: auto; (default) will show the default context menu if contentEditable is true OR text has been selected OR element is input or textarea
--default-contextmenu: show; will always show the default context menu
--default-contextmenu: hide; will always hide the default context menu
This rule is inherited like normal CSS rules, so nesting works as expected
*/
export function processDefaultContextMenu(event) {
// Process default context menu
const element = event.target;
const computedStyle = window.getComputedStyle(element);
const defaultContextMenuAction = computedStyle.getPropertyValue("--default-contextmenu").trim();
switch (defaultContextMenuAction) {
case "show":
return;
case "hide":
event.preventDefault();
return;
default:
// Check if contentEditable is true
if (element.isContentEditable) {
return;
}
// Check if text has been selected and action is on the selected elements
const selection = window.getSelection();
const hasSelection = (selection.toString().length > 0)
if (hasSelection) {
for (let i = 0; i < selection.rangeCount; i++) {
const range = selection.getRangeAt(i);
const rects = range.getClientRects();
for (let j = 0; j < rects.length; j++) {
const rect = rects[j];
if (document.elementFromPoint(rect.left, rect.top) === element) {
return;
}
}
}
}
// Check if tagname is input or textarea
if (element.tagName === "INPUT" || element.tagName === "TEXTAREA") {
if (hasSelection || (!element.readOnly && !element.disabled)) {
return;
}
}
// hide default context menu
event.preventDefault();
}
}

View File

@ -16,6 +16,7 @@ import * as Window from "./window";
import * as Screen from "./screen"; import * as Screen from "./screen";
import * as Browser from "./browser"; import * as Browser from "./browser";
import * as Clipboard from "./clipboard"; import * as Clipboard from "./clipboard";
import * as ContextMenu from "./contextmenu";
export function Quit() { export function Quit() {
@ -61,7 +62,7 @@ window.wails = {
callbacks, callbacks,
flags: { flags: {
disableScrollbarDrag: false, disableScrollbarDrag: false,
disableWailsDefaultContextMenu: false, disableDefaultContextMenu: false,
enableResize: false, enableResize: false,
defaultCursor: null, defaultCursor: null,
borderThickness: 6, borderThickness: 6,
@ -78,10 +79,8 @@ if (window.wailsbindings) {
delete window.wails.SetBindings; delete window.wails.SetBindings;
} }
// This is evaluated at build time in package.json // (bool) This is evaluated at build time in package.json
// const dev = 0; if (!DEBUG) {
// const production = 1;
if (ENV === 1) {
delete window.wailsbindings; delete window.wailsbindings;
} }
@ -189,8 +188,13 @@ window.addEventListener('mousemove', function (e) {
// Setup context menu hook // Setup context menu hook
window.addEventListener('contextmenu', function (e) { window.addEventListener('contextmenu', function (e) {
if (window.wails.flags.disableWailsDefaultContextMenu) { // always show the contextmenu in debug & dev
if (DEBUG) return;
if (window.wails.flags.disableDefaultContextMenu) {
e.preventDefault(); e.preventDefault();
} else {
ContextMenu.processDefaultContextMenu(e);
} }
}); });

View File

@ -7,8 +7,8 @@
"build": "run-p build:*", "build": "run-p build:*",
"build:ipc-desktop": "npx esbuild desktop/ipc.js --bundle --minify --outfile=ipc.js", "build:ipc-desktop": "npx esbuild desktop/ipc.js --bundle --minify --outfile=ipc.js",
"build:ipc-dev": "cd dev && npm install && npm run build", "build:ipc-dev": "cd dev && npm install && npm run build",
"build:runtime-desktop-prod": "npx esbuild desktop/main.js --bundle --minify --outfile=runtime_prod_desktop.js --define:ENV=1", "build:runtime-desktop-prod": "npx esbuild desktop/main.js --bundle --minify --outfile=runtime_prod_desktop.js --define:DEBUG=false",
"build:runtime-desktop-dev": "npx esbuild desktop/main.js --bundle --sourcemap=inline --outfile=runtime_dev_desktop.js --define:ENV=0", "build:runtime-desktop-debug": "npx esbuild desktop/main.js --bundle --sourcemap=inline --outfile=runtime_debug_desktop.js --define:DEBUG=true",
"test": "vitest" "test": "vitest"
}, },
"author": "Lea Anthony <lea.anthony@gmail.com>", "author": "Lea Anthony <lea.anthony@gmail.com>",

View File

@ -0,0 +1,8 @@
//go:build debug || !production
package runtime
import _ "embed"
//go:embed runtime_debug_desktop.js
var RuntimeDesktopJS []byte

File diff suppressed because one or more lines are too long

View File

@ -1,8 +0,0 @@
//go:build dev || bindings || (!dev && !production && !bindings)
package runtime
import _ "embed"
//go:embed runtime_dev_desktop.js
var RuntimeDesktopJS []byte

File diff suppressed because one or more lines are too long

View File

@ -1,4 +1,4 @@
//go:build production //go:build production && !debug
package runtime package runtime

File diff suppressed because one or more lines are too long

Some files were not shown because too many files have changed in this diff Show More