diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml
index a13ad60c6..f1f9371d2 100644
--- a/.github/FUNDING.yml
+++ b/.github/FUNDING.yml
@@ -1,6 +1,6 @@
# These are supported funding model platforms
-github: [leaanthony]
+github: [ leaanthony ]
patreon: # Replace with a single Patreon username
open_collective: # Replace with a single Open Collective username
ko_fi: # Replace with a single Ko-fi username
diff --git a/.github/workflows/deploy-website-to-wails.top-mirror.yml b/.github/workflows/deploy-website-to-wails.top-mirror.yml
new file mode 100644
index 000000000..88966f189
--- /dev/null
+++ b/.github/workflows/deploy-website-to-wails.top-mirror.yml
@@ -0,0 +1,35 @@
+name: Deploy mirror | 部署镜像
+
+on:
+ push:
+ branches: [master]
+ # pull_request:
+ # branches: [ main ]
+
+jobs:
+ build-and-deploy:
+ name: Automatic deployment | 自动部署
+ runs-on: ubuntu-latest
+ if: github.repository == 'misitebao/wails'
+
+ steps:
+ - name: Checkout | 切换到部署分支
+ uses: actions/checkout@v2
+ with:
+ ref: "master"
+ submodules: true
+ fetch-depth: 0
+
+ - name: Build Site | 构建网站
+ run: |
+ cd website &&
+ npm install && npm run build
+
+ - name: Deploy to Server | 部署到服务器
+ uses: hengkx/ssh-deploy@v1.0.1
+ with:
+ HOST: ${{ secrets.DEPLOY_HOST }}
+ USERNAME: ${{ secrets.DEPLOY_HOST_USER }}
+ PASSWORD: ${{ secrets.DEPLOY_HOST_PASSWORD }}
+ SOURCE: "website/build"
+ TARGET: "/www/wwwroot/wails.top"
diff --git a/.github/workflows/latest-pre.yml b/.github/workflows/latest-pre.yml
index d7c865a37..870fe55d5 100644
--- a/.github/workflows/latest-pre.yml
+++ b/.github/workflows/latest-pre.yml
@@ -1,8 +1,10 @@
name: latest pre-release
on:
push:
+ branches:
+ - develop
tags:
- - '**-pre**'
+ - '**-pre**'
jobs:
build:
diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml
index 4ecf5c57e..df5e53697 100644
--- a/.github/workflows/pr.yml
+++ b/.github/workflows/pr.yml
@@ -29,4 +29,4 @@ jobs:
run: go build -v ./cmd/wails
- name: Test
- run: ./wails version
\ No newline at end of file
+ run: ./wails version
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index c22c6bb48..03fe71f98 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -31,4 +31,4 @@ jobs:
run: go build -v ./cmd/wails
- name: Test
- run: ./wails version
\ No newline at end of file
+ run: ./wails version
diff --git a/.github/workflows/runtime.yml b/.github/workflows/runtime.yml
new file mode 100644
index 000000000..43cc5bdff
--- /dev/null
+++ b/.github/workflows/runtime.yml
@@ -0,0 +1,29 @@
+name: Runtime
+on:
+ push:
+ branches:
+ - v2-alpha
+ paths:
+ - 'v2/internal/frontend/runtime/**'
+jobs:
+ rebuild-runtime:
+ name: Rebuild the runtime
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v2
+ - uses: actions/setup-node@v2
+ with:
+ node-version: 14.17.6
+ cache: 'npm'
+ cache-dependency-path: v2/internal/frontend/runtime/package-lock.json
+ - run: npm install
+ working-directory: v2/internal/frontend/runtime
+ - run: npm run build
+ working-directory: v2/internal/frontend/runtime
+
+ - name: Commit changes
+ uses: devops-infra/action-commit-push@master
+ with:
+ github_token: "${{ secrets.GITHUB_TOKEN }}"
+ commit_prefix: "[AUTO]"
+ commit_message: "The runtime was rebuilt"
diff --git a/.gitignore b/.gitignore
index e2476fdc9..620386a67 100644
--- a/.gitignore
+++ b/.gitignore
@@ -17,8 +17,17 @@ cmd/wails/wails
.DS_Store
tmp
node_modules/
+package.json.md5
+v2/test/**/frontend/dist
+v2/test/**/build/
+v2/test/frameless/icon.png
+v2/test/hidden/icon.png
+v2/test/kitchensink/frontend/public/bundle.*
+v2/pkg/parser/testproject/frontend/wails
v2/test/kitchensink/frontend/public
-v2/internal/ffenestri/runtime.c
-v2/internal/runtime/assets/desktop.js
v2/test/kitchensink/build/darwin/desktop/kitchensink
v2/test/kitchensink/frontend/package.json.md5
+/v2/internal/ffenestri/windows/test/cmake-build-debug/
+!v2/internal/ffenestri/windows/x64/webview2.dll
+!v2/internal/ffenestri/windows/x64/WebView2Loader.dll
+.idea/
diff --git a/.vscode/settings.json b/.vscode/settings.json
index dde13a901..da2d84ba6 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -1,4 +1,8 @@
{
"go.formatTool": "goimports",
- "eslint.alwaysShowStatus": true
+ "eslint.alwaysShowStatus": true,
+ "files.associations": {
+ "__locale": "c",
+ "ios": "c"
+ }
}
\ No newline at end of file
diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md
index d5119e928..72d6bd9d9 100644
--- a/CONTRIBUTORS.md
+++ b/CONTRIBUTORS.md
@@ -31,18 +31,18 @@ Wails is what it is because of the time and effort given by these great people.
* [Christopher Murphy](https://github.com/Splode)
* [Zámbó, Levente](https://github.com/Lyimmi)
* [artem](https://github.com/Unix4ever)
- * [Tim Kipp](https://github.com/timkippdev)
- * [Dmitry Gomzyakov](https://github.com/kyoto44)
- * [Arthur Wiebe](https://github.com/artooro)
- * [Ilgıt Yıldırım](https://github.com/ilgityildirim)
- * [Altynbek](https://github.com/gelleson)
- * [Kyle](https://github.com/kmuchmore)
- * [Balakrishna Prasad Ganne](https://github.com/aayush420)
- * [Charaf Rezrazi](https://github.com/Rezrazi)
- * [misitebao](https://github.com/misitebao)
- * [Elie Grenon](https://github.com/DrunkenPoney)
- * [SophieAu](https://github.com/SophieAu)
- * [Alexander Matviychuk](https://github.com/alexmat)
- * [RH12503](https://github.com/RH12503)
- * [hi019](https://github.com/hi019)
- * [Igor Minen](https://github.com/Igogrek)
+* [Tim Kipp](https://github.com/timkippdev)
+* [Dmitry Gomzyakov](https://github.com/kyoto44)
+* [Arthur Wiebe](https://github.com/artooro)
+* [Ilgıt Yıldırım](https://github.com/ilgityildirim)
+* [Altynbek](https://github.com/gelleson)
+* [Kyle](https://github.com/kmuchmore)
+* [Balakrishna Prasad Ganne](https://github.com/aayush420)
+* [Charaf Rezrazi](https://github.com/Rezrazi)
+* [misitebao](https://github.com/misitebao)
+* [Elie Grenon](https://github.com/DrunkenPoney)
+* [SophieAu](https://github.com/SophieAu)
+* [Alexander Matviychuk](https://github.com/alexmat)
+* [RH12503](https://github.com/RH12503)
+* [hi019](https://github.com/hi019)
+* [Igor Minen](https://github.com/Igogrek)
diff --git a/README.md b/README.md
index 782d57e1f..545fd231a 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,5 @@
-
+
Build desktop applications using Go & Web Technologies.
@@ -18,12 +18,16 @@
## Internationalization
-English | [简体中文](README.zh_CN.md)
+English | [简体中文](README.zh-Hans.md)
-The traditional method of providing web interfaces to Go programs is via a built-in web server. Wails offers a different approach: it provides the ability to wrap both Go code and a web frontend into a single binary. Tools are provided to make this easy for you by handling project creation, compilation and bundling. All you have to do is get creative!
+The traditional method of providing web interfaces to Go programs is via a built-in web server. Wails offers a different
+approach: it provides the ability to wrap both Go code and a web frontend into a single binary. Tools are provided to
+make this easy for you by handling project creation, compilation and bundling. All you have to do is get creative!
The official docs can be found at [https://wails.app](https://wails.app).
+Click [here](https://wails.io) if you are interested in trying out v2 Beta for Windows.
+
## Contents
@@ -33,22 +37,21 @@ The official docs can be found at [https://wails.app](https://wails.app).
- [3. Features](#nav-3)
- [4. Sponsors](#nav-4)
- [5. Installation](#nav-5)
- - [5.1 MacOS](#nav-5-1)
- - [5.2 Linux](#nav-5-2)
- - [5.2.1 Debian/Ubuntu](#nav-5-2-1)
- - [5.2.2 Arch Linux / ArchLabs / Ctlos Linux](#nav-5-2-2)
- - [5.2.3 Centos](#nav-5-2-3)
- - [5.2.4 Fedora](#nav-5-2-4)
- - [5.2.5 VoidLinux & VoidLinux-musl](#nav-5-2-5)
- - [5.2.6 Gentoo](#nav-5-2-6)
- - [5.3 Windows](#nav-5-3)
+ - [5.1 MacOS](#nav-5-1)
+ - [5.2 Linux](#nav-5-2)
+ - [5.2.1 Debian/Ubuntu](#nav-5-2-1)
+ - [5.2.2 Arch Linux / ArchLabs / Ctlos Linux](#nav-5-2-2)
+ - [5.2.3 Centos](#nav-5-2-3)
+ - [5.2.4 Fedora](#nav-5-2-4)
+ - [5.2.5 VoidLinux & VoidLinux-musl](#nav-5-2-5)
+ - [5.2.6 Gentoo](#nav-5-2-6)
+ - [5.3 Windows](#nav-5-3)
- [6. Installation](#nav-6)
- [7. Next Steps](#nav-7)
- [8. FAQ](#nav-8)
- [9. Contributors](#nav-9)
- [10. Special Mentions](#nav-10)
-- [11. Licensing](#nav-11)
-- [12. Special Thanks](#nav-12)
+- [11. Special Thanks](#nav-11)
@@ -70,33 +73,81 @@ The official docs can be found at [https://wails.app](https://wails.app).
This project is supported by these kind people / companies:
-
-
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
+
+
-
-
+
+
-
-
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
## Installation
-Wails uses cgo to bind to the native rendering engines so a number of platform dependent libraries are needed as well as an installation of Go. The basic requirements are:
+Wails uses cgo to bind to the native rendering engines so a number of platform dependent libraries are needed as well as
+an installation of Go. The basic requirements are:
- Go 1.16
- npm
@@ -165,7 +216,9 @@ _Fedora 29, 30_
### Windows
-Windows requires gcc and related tooling. The recommended download is from [http://tdm-gcc.tdragon.net/download](http://tdm-gcc.tdragon.net/download). Once this is installed, you are good to go.
+Windows requires gcc and related tooling. The recommended download is
+from [http://tdm-gcc.tdragon.net/download](http://tdm-gcc.tdragon.net/download). Once this is installed, you are good to
+go.
@@ -191,15 +244,20 @@ It is recommended at this stage to read the comprehensive documentation at [http
- Is this an alternative to Electron?
- Depends on your requirements. It's designed to make it easy for Go programmers to make lightweight desktop applications or add a frontend to their existing applications. Whilst Wails does not currently offer hooks into native elements such as menus, this may change in the future.
+ Depends on your requirements. It's designed to make it easy for Go programmers to make lightweight desktop
+ applications or add a frontend to their existing applications. Whilst Wails does not currently offer hooks into native
+ elements such as menus, this may change in the future.
- Who is this project aimed at?
- Go programmers who want to bundle an HTML/JS/CSS frontend with their applications, without resorting to creating a server and opening a browser to view it.
+ Go programmers who want to bundle an HTML/JS/CSS frontend with their applications, without resorting to creating a
+ server and opening a browser to view it.
- What's with the name?
- When I saw WebView, I thought "What I really want is tooling around building a WebView app, a bit like Rails is to Ruby". So initially it was a play on words (Webview on Rails). It just so happened to also be a homophone of the English name for the [Country](https://en.wikipedia.org/wiki/Wales) I am from. So it stuck.
+ When I saw WebView, I thought "What I really want is tooling around building a WebView app, a bit like Rails is to
+ Ruby". So initially it was a play on words (Webview on Rails). It just so happened to also be a homophone of the
+ English name for the [Country](https://en.wikipedia.org/wiki/Wales) I am from. So it stuck.
@@ -250,6 +308,7 @@ It is recommended at this stage to read the comprehensive documentation at [http
+
@@ -257,9 +316,12 @@ It is recommended at this stage to read the comprehensive documentation at [http
Without the following people, this project would never have existed:
-- [Dustin Krysak](https://wiki.ubuntu.com/bashfulrobot) - His support and feedback has been immense. More patience than you can throw a stick at (Not long now Dustin!).
-- [Serge Zaitsev](https://github.com/zserge) - Creator of [Webview](https://github.com/zserge/webview) which Wails uses for the windowing.
-- [Byron](https://github.com/bh90210) - At times, Byron has single handedly kept this project alive. Without his incredible input, we never would have got to v1.
+- [Dustin Krysak](https://wiki.ubuntu.com/bashfulrobot) - His support and feedback has been immense. More patience than
+ you can throw a stick at (Not long now Dustin!).
+- [Serge Zaitsev](https://github.com/zserge) - Creator of [Webview](https://github.com/zserge/webview) which Wails uses
+ for the windowing.
+- [Byron](https://github.com/bh90210) - At times, Byron has single handedly kept this project alive. Without his
+ incredible input, we never would have got to v1.
This project was mainly coded to the following albums:
@@ -279,17 +341,11 @@ This project was mainly coded to the following albums:
-## Licensing
-
-[](https://app.fossa.io/projects/git%2Bgithub.com%2Fwailsapp%2Fwails?ref=badge_large)
-
-
-
## Special Thanks
- A *huge* thanks to Pace for sponsoring the project and helping the efforts to get Wails ported to Apple Silicon!
+ A huge thanks to Pace for sponsoring the project and helping the efforts to get Wails ported to Apple Silicon!
If you are looking for a Project Management tool that's powerful but quick and easy to use, check them out!
diff --git a/README.zh_CN.md b/README.zh-Hans.md
similarity index 68%
rename from README.zh_CN.md
rename to README.zh-Hans.md
index 547adc16d..fc310183e 100644
--- a/README.zh_CN.md
+++ b/README.zh-Hans.md
@@ -1,5 +1,5 @@
-
+
使用 Go 和 Web 技术构建桌面应用程序。
@@ -20,10 +20,12 @@
[English](README.md) | 简体中文
-向 Go 程序提供 Web 接口的传统方法是通过内置 Web 服务器。Wails 提供了一种不同的方法:它提供了将 Go 代码和 Web 前端都包装成单个二进制文件的能力。通过处理项目创建、编译和打包,可为您提供工具,使您轻松做到这一点。你所要做的就是发挥创造力!
+向 Go 程序提供 Web 接口的传统方法是通过内置 Web 服务器。Wails 提供了一种不同的方法:它提供了将 Go 代码和 Web
+前端都包装成单个二进制文件的能力。通过提供工具,可以很轻松的完成项目的创建、编译和打包。你所要做的就是发挥创意!
-官方文档可以在 [https://wails.app](https://wails.app)中找到。
-国内镜像站点 [https://wails.top](https://wails.top)
+官方文档可以在 [https://wails.app](https://wails.app) 中找到。
+
+国内镜像站点 [https://wails.top](https://wails.top)。
@@ -34,15 +36,15 @@
- [3. 特征](#nav-3)
- [4. 赞助商](#nav-4)
- [5. 安装](#nav-5)
- - [5.1 MacOS](#nav-5-1)
- - [5.2 Linux](#nav-5-2)
- - [5.2.1 Debian/Ubuntu](#nav-5-2-1)
- - [5.2.2 Arch Linux / ArchLabs / Ctlos Linux](#nav-5-2-2)
- - [5.2.3 Centos](#nav-5-2-3)
- - [5.2.4 Fedora](#nav-5-2-4)
- - [5.2.5 VoidLinux & VoidLinux-musl](#nav-5-2-5)
- - [5.2.6 Gentoo](#nav-5-2-6)
- - [5.3 Windows](#nav-5-3)
+ - [5.1 MacOS](#nav-5-1)
+ - [5.2 Linux](#nav-5-2)
+ - [5.2.1 Debian/Ubuntu](#nav-5-2-1)
+ - [5.2.2 Arch Linux / ArchLabs / Ctlos Linux](#nav-5-2-2)
+ - [5.2.3 Centos](#nav-5-2-3)
+ - [5.2.4 Fedora](#nav-5-2-4)
+ - [5.2.5 VoidLinux & VoidLinux-musl](#nav-5-2-5)
+ - [5.2.6 Gentoo](#nav-5-2-6)
+ - [5.3 Windows](#nav-5-3)
- [6. 安装](#nav-6)
- [7. 下一步](#nav-7)
- [8. 常见问题](#nav-8)
@@ -71,29 +73,81 @@
这个项目由以下这些人或者公司支持:
-
-
-
-
+
+
+
-
-
+
+
-
-
+
+
-
-
+
+
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
## 安装
-Wails 使用 cgo 与原生渲染引擎结合,因此需要一些依赖平台的库以及 Go 的安装。基本要求是:
+Wails 使用 cgo 与原生渲染引擎结合,因此需要依赖一些平台的库以及 Go 的安装。基本要求是:
- Go 1.16
- npm
@@ -120,7 +174,7 @@ _Debian: 8, 9, 10_
_Ubuntu: 16.04, 18.04, 19.04_
-_Also succesfully tested on: Zorin 15, Parrot 4.7, Linuxmint 19, Elementary 5, Kali, Neon_, Pop!\_OS
+_也成功测试了: Zorin 15, Parrot 4.7, Linuxmint 19, Elementary 5, Kali, Neon_, Pop!\_OS
@@ -128,7 +182,7 @@ _Also succesfully tested on: Zorin 15, Parrot 4.7, Linuxmint 19, Elementary 5, K
`sudo pacman -S webkit2gtk gtk3`
-_Also succesfully test on: Manjaro & ArcoLinux_
+_也成功测试了: Manjaro & ArcoLinux_
@@ -162,13 +216,13 @@ _Fedora 29, 30_
### Windows
-Windows 需要 GCC 和相关工具。 建议从 [http://tdm-gcc.tdragon.net/download](http://tdm-gcc.tdragon.net/download)下载, 安装完成,您就可以开始了。
+Windows 需要 GCC 和相关工具。 建议从 [http://tdm-gcc.tdragon.net/download](http://tdm-gcc.tdragon.net/download) 下载, 安装完成,您就可以开始了。
## 安装
-**确保 Go modules 是开启的: GO111MODULE=on 并且 go/bin 在您的 PATH 变量中.**
+**确保 Go modules 是开启的:GO111MODULE=on 并且 go/bin 在您的 PATH 变量中。**
安装很简单,运行以下命令:
@@ -180,7 +234,7 @@ go get -u github.com/wailsapp/wails/cmd/wails
## 下一步
-建议在此时阅读[https://wails.app](https://wails.app)上面的文档.
+建议在此时阅读 [https://wails.app](https://wails.app) 上面的文档.
@@ -188,15 +242,16 @@ go get -u github.com/wailsapp/wails/cmd/wails
- 它是 Electron 的替代品吗?
- 取决于您的要求。它旨在使 Go 程序员可以轻松制作轻量级桌面应用程序或在其现有应用程序中添加前端。尽管 Wails 当前不提供对诸如菜单之类的本机元素的钩子,但将来可能会改变。
+ 取决于您的要求。它旨在使 Go 程序员可以轻松制作轻量级桌面应用程序或在其现有应用程序中添加前端。尽管 Wails 当前不提供对诸如菜单之类的原生元素的钩子,但将来可能会改变。
- 这个项目针对的是谁?
- 希望将 HTML / JS / CSS 前端与其应用程序捆绑在一起的程序员,而无需借助创建服务并打开浏览器进行查看的方式。
+ 希望将 HTML / JS / CSS 前端与其应用程序捆绑在一起的程序员,而不是借助创建服务并打开浏览器进行查看的方式。
- 名字怎么来的?
- 当我看到 WebView 时,我想"我真正想要的是围绕构建 WebView 应用程序工作,有点像 Rails 对于 Ruby"。因此,最初它是一个文字游戏(Webview on Rails)。碰巧也是我来自的[国家](https://en.wikipedia.org/wiki/Wales)的英文名字的同音。所以就是他了。
+ 当我看到 WebView 时,我想"我真正想要的是围绕构建 WebView 应用程序工作,有点像 Rails 对于 Ruby"。因此,最初它是一个文字游戏(Webview on
+ Rails)。碰巧也是我来自的 [国家](https://en.wikipedia.org/wiki/Wales) 的英文名字的同音。所以就是他了。
@@ -252,11 +307,11 @@ go get -u github.com/wailsapp/wails/cmd/wails
## 特别提及
-如果没有以下人员,此项目将永远不会存在:
+如果没有以下人员,此项目或许永远不会存在:
-- [Dustin Krysak](https://wiki.ubuntu.com/bashfulrobot) - His support and feedback has been immense. More patience than you can throw a stick at (Not long now Dustin!).
-- [Serge Zaitsev](https://github.com/zserge) - Creator of [Webview](https://github.com/zserge/webview) which Wails uses for the windowing.
-- [Byron](https://github.com/bh90210) - At times, Byron has single handedly kept this project alive. Without his incredible input, we never would have got to v1.
+- [Dustin Krysak](https://wiki.ubuntu.com/bashfulrobot) - 他的支持和反馈是巨大的。
+- [Serge Zaitsev](https://github.com/zserge) - Wails 窗口所使用的 [Webview](https://github.com/zserge/webview) 的作者。
+- [Byron](https://github.com/bh90210) - 有时,Byron 单枪匹马地保持这个项目活着。没有他令人难以置信的投入,我们永远不会得到 v1 。
This project was mainly coded to the following albums:
@@ -286,12 +341,12 @@ This project was mainly coded to the following albums:
- 非常感谢Pace 对项目的赞助,并帮助将Wails移植到Apple Silicon
- 如果您正在寻找一个强大的项目管理工具,并且快速和易于使用,可以看看他们!
+ 非常 感谢Pace 对项目的赞助,并帮助将 Wails 移植到 Apple Silicon !
+ 如果您正在寻找一个强大并且快速和易于使用的项目管理工具,可以看看他们!
- 特别感谢JetBrains向我们捐赠许可!
- 请点击logo让他们知道你的感激之情!
+ 特别感谢 JetBrains 向我们捐赠许可!
+ 请点击 logo 让他们知道你的感激之情!
diff --git a/app_other.go b/app_other.go
index 5d63c4c6c..9e0514350 100644
--- a/app_other.go
+++ b/app_other.go
@@ -1,3 +1,4 @@
+//go:build linux || darwin || !windows
// +build linux darwin !windows
package wails
diff --git a/app_windows.go b/app_windows.go
index 6386d4131..cf9472731 100644
--- a/app_windows.go
+++ b/app_windows.go
@@ -1,3 +1,4 @@
+//go:build windows || !linux || !darwin
// +build windows !linux !darwin
package wails
diff --git a/cmd/linux.go b/cmd/linux.go
index 8ef7836ac..902a75b46 100644
--- a/cmd/linux.go
+++ b/cmd/linux.go
@@ -73,6 +73,9 @@ const (
RHEL
// NixOS distribution
NixOS
+ // Artix linux distribution
+ ArtixLinux
+
)
// DistroInfo contains all the information relating to a linux distribution
@@ -187,6 +190,8 @@ func parseOsRelease(osRelease string) *DistroInfo {
result.Distribution = Crux
case "nixos":
result.Distribution = NixOS
+ case "artix":
+ result.Distribution = ArtixLinux
default:
result.Distribution = Unknown
}
diff --git a/cmd/linuxdb.yaml b/cmd/linuxdb.yaml
index 52f6a57cd..64628a5ea 100644
--- a/cmd/linuxdb.yaml
+++ b/cmd/linuxdb.yaml
@@ -213,6 +213,15 @@ distributions:
gccversioncommand: *gccdumpversion
programs: *archdefaultprograms
libraries: *archdefaultlibraries
+ artix:
+ id: artix
+ releases:
+ default:
+ version: default
+ name: Artix Linux
+ gccversioncommand: *gccdumpversion
+ programs: *archdefaultprograms
+ libraries: *archdefaultlibraries
ctlos:
id: ctlos
releases:
@@ -364,4 +373,3 @@ distributions:
help: Please install with `nix-env -iA nixos.gtk3`
- name: webkitgtk
help: Please install with `nix-env -iA nixos.nodePackages.webkitgtk`
-
diff --git a/cmd/system.go b/cmd/system.go
index 5c2aa6f3c..49e4f760f 100644
--- a/cmd/system.go
+++ b/cmd/system.go
@@ -281,7 +281,7 @@ func CheckDependencies(logger *Logger) (bool, error) {
switch distroInfo.Distribution {
case Ubuntu, Debian, Zorin, Parrot, Linuxmint, Elementary, Kali, Neon, Deepin, Raspbian, PopOS:
libraryChecker = DpkgInstalled
- case Arch, ArcoLinux, ArchLabs, Ctlos, Manjaro, ManjaroARM, EndeavourOS:
+ case Arch, ArcoLinux, ArchLabs, Ctlos, Manjaro, ManjaroARM, EndeavourOS, ArtixLinux:
libraryChecker = PacmanInstalled
case CentOS, Fedora, Tumbleweed, Leap, RHEL:
libraryChecker = RpmInstalled
diff --git a/cmd/templates/svelte/frontend/rollup.config.js b/cmd/templates/svelte/frontend/rollup.config.js
index ac3a0a769..6d0a0a12d 100644
--- a/cmd/templates/svelte/frontend/rollup.config.js
+++ b/cmd/templates/svelte/frontend/rollup.config.js
@@ -2,7 +2,7 @@ import svelte from 'rollup-plugin-svelte';
import resolve from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';
import livereload from 'rollup-plugin-livereload';
-import { terser } from 'rollup-plugin-terser';
+import {terser} from 'rollup-plugin-terser';
import image from '@rollup/plugin-image';
import babel from 'rollup-plugin-babel';
import polyfill from 'rollup-plugin-polyfill';
diff --git a/cmd/templates/vue3-js/frontend/README.md b/cmd/templates/vue3-js/frontend/README.md
index 8d5cc5314..f56df6be7 100644
--- a/cmd/templates/vue3-js/frontend/README.md
+++ b/cmd/templates/vue3-js/frontend/README.md
@@ -1,24 +1,29 @@
# vue-js
## Project setup
+
```
npm install
```
### Compiles and hot-reloads for development
+
```
npm run serve
```
### Compiles and minifies for production
+
```
npm run build
```
### Lints and fixes files
+
```
npm run lint
```
### Customize configuration
+
See [Configuration Reference](https://cli.vuejs.org/config/).
diff --git a/cmd/templates/vue3-js/frontend/babel.config.js b/cmd/templates/vue3-js/frontend/babel.config.js
index e9558405f..c94e72931 100644
--- a/cmd/templates/vue3-js/frontend/babel.config.js
+++ b/cmd/templates/vue3-js/frontend/babel.config.js
@@ -1,5 +1,5 @@
module.exports = {
- presets: [
- '@vue/cli-plugin-babel/preset'
- ]
+ presets: [
+ '@vue/cli-plugin-babel/preset'
+ ]
}
diff --git a/cmd/templates/vue3-js/frontend/public/index.html b/cmd/templates/vue3-js/frontend/public/index.html
index 3e5a13962..6ba8b205d 100644
--- a/cmd/templates/vue3-js/frontend/public/index.html
+++ b/cmd/templates/vue3-js/frontend/public/index.html
@@ -1,17 +1,18 @@
-
+
-
-
-
+
+
+
<%= htmlWebpackPlugin.options.title %>
-
-
-
- We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.
-
-
-
-
+
+
+
+ We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled.
+ Please enable it to continue.
+
+
+
+
diff --git a/cmd/templates/vue3-js/frontend/src/main.js b/cmd/templates/vue3-js/frontend/src/main.js
index c65e18a02..fb6c9ce07 100644
--- a/cmd/templates/vue3-js/frontend/src/main.js
+++ b/cmd/templates/vue3-js/frontend/src/main.js
@@ -1,4 +1,4 @@
-import { createApp } from 'vue'
+import {createApp} from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
@@ -8,7 +8,7 @@ import * as Wails from '@wailsapp/runtime';
Wails.Init(() => {
createApp(App)
- .use(store)
- .use(router)
- .mount('#app')
+ .use(store)
+ .use(router)
+ .mount('#app')
})
diff --git a/cmd/templates/vue3-js/frontend/src/router/index.js b/cmd/templates/vue3-js/frontend/src/router/index.js
index 38211ad79..41f7ce976 100644
--- a/cmd/templates/vue3-js/frontend/src/router/index.js
+++ b/cmd/templates/vue3-js/frontend/src/router/index.js
@@ -1,4 +1,4 @@
-import { createRouter, createMemoryHistory } from 'vue-router'
+import {createMemoryHistory, createRouter} from 'vue-router'
import Home from '../views/Home.vue'
import About from '../views/About.vue'
diff --git a/cmd/templates/vue3-js/frontend/src/store/index.js b/cmd/templates/vue3-js/frontend/src/store/index.js
index 5f05f1939..a747c1ce9 100644
--- a/cmd/templates/vue3-js/frontend/src/store/index.js
+++ b/cmd/templates/vue3-js/frontend/src/store/index.js
@@ -1,12 +1,8 @@
-import { createStore } from 'vuex'
+import {createStore} from 'vuex'
export default createStore({
- state: {
- },
- mutations: {
- },
- actions: {
- },
- modules: {
- }
+ state: {},
+ mutations: {},
+ actions: {},
+ modules: {}
})
diff --git a/cmd/templates/vue3-js/frontend/vue.config.js b/cmd/templates/vue3-js/frontend/vue.config.js
index 8dcf3e339..72e4fd1d5 100644
--- a/cmd/templates/vue3-js/frontend/vue.config.js
+++ b/cmd/templates/vue3-js/frontend/vue.config.js
@@ -1,42 +1,42 @@
let cssConfig = {};
if (process.env.NODE_ENV == 'production') {
- cssConfig = {
- extract: {
- filename: '[name].css',
- chunkFilename: '[name].css'
- }
- };
+ cssConfig = {
+ extract: {
+ filename: '[name].css',
+ chunkFilename: '[name].css'
+ }
+ };
}
module.exports = {
- chainWebpack: config => {
- let limit = 9999999999999999;
- config.module
- .rule('images')
- .test(/\.(png|gif|jpg)(\?.*)?$/i)
- .use('url-loader')
- .loader('url-loader')
- .tap(options => Object.assign(options, { limit: limit }));
- config.module
- .rule('fonts')
- .test(/\.(woff2?|eot|ttf|otf|svg)(\?.*)?$/i)
- .use('url-loader')
- .loader('url-loader')
- .options({
- limit: limit
- });
- },
- css: cssConfig,
- configureWebpack: {
- output: {
- filename: '[name].js'
- },
- optimization: {
- splitChunks: false
- }
- },
- devServer: {
- disableHostCheck: true
- }
+ chainWebpack: config => {
+ let limit = 9999999999999999;
+ config.module
+ .rule('images')
+ .test(/\.(png|gif|jpg)(\?.*)?$/i)
+ .use('url-loader')
+ .loader('url-loader')
+ .tap(options => Object.assign(options, {limit: limit}));
+ config.module
+ .rule('fonts')
+ .test(/\.(woff2?|eot|ttf|otf|svg)(\?.*)?$/i)
+ .use('url-loader')
+ .loader('url-loader')
+ .options({
+ limit: limit
+ });
+ },
+ css: cssConfig,
+ configureWebpack: {
+ output: {
+ filename: '[name].js'
+ },
+ optimization: {
+ splitChunks: false
+ }
+ },
+ devServer: {
+ disableHostCheck: true
+ }
};
diff --git a/cmd/templates/vue3-js/template.json b/cmd/templates/vue3-js/template.json
index 3d70af3bc..8cde55215 100644
--- a/cmd/templates/vue3-js/template.json
+++ b/cmd/templates/vue3-js/template.json
@@ -11,5 +11,8 @@
"serve": "npm run serve",
"bridge": "src",
"wailsdir": "",
- "platforms": ["linux", "darwin"]
+ "platforms": [
+ "linux",
+ "darwin"
+ ]
}
diff --git a/cmd/wails/10.1_dev_newtemplate.go b/cmd/wails/10.1_dev_newtemplate.go
index 3c52b45a9..17e4a4c1e 100644
--- a/cmd/wails/10.1_dev_newtemplate.go
+++ b/cmd/wails/10.1_dev_newtemplate.go
@@ -1,3 +1,4 @@
+//go:build dev
// +build dev
package main
diff --git a/cmd/wails/10_dev.go b/cmd/wails/10_dev.go
index 3d237cb98..ea0af0976 100644
--- a/cmd/wails/10_dev.go
+++ b/cmd/wails/10_dev.go
@@ -1,3 +1,4 @@
+//go:build dev
// +build dev
package main
diff --git a/cmd/windows.go b/cmd/windows.go
index 774730f74..1a85f13c1 100644
--- a/cmd/windows.go
+++ b/cmd/windows.go
@@ -1,3 +1,4 @@
+//go:build windows
// +build windows
package cmd
diff --git a/config.go b/config.go
index 3833dfdae..0fc80c255 100644
--- a/config.go
+++ b/config.go
@@ -181,7 +181,7 @@ func newConfig(userConfig *AppConfig) (*AppConfig, error) {
MaxWidth: -1,
MaxHeight: -1,
Title: "My Wails App",
- Colour: "",
+ Colour: "",
HTML: defaultHTML,
}
diff --git a/go.mod b/go.mod
index ff37b58d6..4d289fe39 100644
--- a/go.mod
+++ b/go.mod
@@ -5,7 +5,7 @@ require (
github.com/abadojack/whatlanggo v1.0.1
github.com/fatih/color v1.7.0
github.com/go-playground/colors v1.2.0
- github.com/gorilla/websocket v1.4.0
+ github.com/gorilla/websocket v1.4.1
github.com/jackmordaunt/icns v1.0.0
github.com/kennygrant/sanitize v1.2.4
github.com/konsorten/go-windows-terminal-sequences v1.0.2 // indirect
@@ -16,12 +16,13 @@ require (
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // indirect
github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4
github.com/pkg/errors v0.8.1 // indirect
- github.com/sirupsen/logrus v1.4.1
+ github.com/sirupsen/logrus v1.8.1
+ github.com/stretchr/objx v0.1.1 // indirect
github.com/stretchr/testify v1.3.0 // indirect
github.com/syossan27/tebata v0.0.0-20180602121909-b283fe4bc5ba
golang.org/x/image v0.0.0-20200430140353-33d19683fad8
golang.org/x/net v0.0.0-20200625001655-4c5254603344 // indirect
- golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd
+ golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359
golang.org/x/text v0.3.0
gopkg.in/AlecAivazis/survey.v1 v1.8.4
gopkg.in/yaml.v3 v3.0.0-20190709130402-674ba3eaed22
diff --git a/go.sum b/go.sum
index 2c697c813..79a777e39 100644
--- a/go.sum
+++ b/go.sum
@@ -11,8 +11,8 @@ github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/go-playground/colors v1.2.0 h1:0EdjTXKrr2g1L/LQTYtIqabeHpZuGZz1U4osS1T8+5M=
github.com/go-playground/colors v1.2.0/go.mod h1:miw1R2JIE19cclPxsXqNdzLZsk4DP4iF+m88bRc7kfM=
-github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q=
-github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
+github.com/gorilla/websocket v1.4.1 h1:q7AeDBpnBk8AogcD4DSag/Ukw/KV+YhzLj2bP5HvKCM=
+github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/hinshun/vt10x v0.0.0-20180616224451-1954e6464174 h1:WlZsjVhE8Af9IcZDGgJGQpNflI3+MJSBhsgT5PCtzBQ=
github.com/hinshun/vt10x v0.0.0-20180616224451-1954e6464174/go.mod h1:DqJ97dSdRW1W22yXSB90986pcOyQ7r45iio1KN2ez1A=
github.com/jackmordaunt/icns v1.0.0 h1:RYSxplerf/l/DUd09AHtITwckkv/mqjVv4DjYdPmAMQ=
@@ -54,6 +54,8 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/sirupsen/logrus v1.4.1 h1:GL2rEmy6nsikmW0r8opw9JIRScdMF5hA8cOYLH7In1k=
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
+github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
+github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
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/testify v1.2.1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
@@ -76,8 +78,12 @@ golang.org/x/sys v0.0.0-20181228144115-9a3f9b0469bb/go.mod h1:STP8DvDyc/dI5b8T5h
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884=
+golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200724161237-0e2f3a69832c h1:UIcGWL6/wpCfyGuJnRFJRurA+yj8RrW7Q6x2YMCXt6c=
+golang.org/x/sys v0.0.0-20200724161237-0e2f3a69832c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359 h1:2B5p2L5IfGiD7+b9BOoRMC6DgObAVZV+Fsp050NqXik=
+golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
gopkg.in/AlecAivazis/survey.v1 v1.8.4 h1:10xXXN3wgIhPheb5NI58zFgZv32Ana7P3Tl4shW+0Qc=
diff --git a/lib/renderer/webview.go b/lib/renderer/webview.go
index d122a3e2b..777a8560c 100644
--- a/lib/renderer/webview.go
+++ b/lib/renderer/webview.go
@@ -24,12 +24,12 @@ import (
var UseFirebug = ""
type WebView struct {
- window wv.WebView // The webview object
- ipc interfaces.IPCManager
- log *logger.CustomLogger
- config interfaces.AppConfig
- eventManager interfaces.EventManager
- bindingCache []string
+ window wv.WebView // The webview object
+ ipc interfaces.IPCManager
+ log *logger.CustomLogger
+ config interfaces.AppConfig
+ eventManager interfaces.EventManager
+ bindingCache []string
maximumSizeSet bool
}
@@ -111,7 +111,7 @@ func (w *WebView) Initialise(config interfaces.AppConfig, ipc interfaces.IPCMana
}
// SignalManager.OnExit(w.Exit)
-
+
// Set colour
color := config.GetColour()
if color != "" {
diff --git a/logo.png b/logo.png
new file mode 100644
index 000000000..8cfad9043
Binary files /dev/null and b/logo.png differ
diff --git a/runtime/js/.eslintrc b/runtime/js/.eslintrc
index 85326fe27..426ccc63d 100644
--- a/runtime/js/.eslintrc
+++ b/runtime/js/.eslintrc
@@ -3,12 +3,12 @@
"browser": true,
"es6": true,
"amd": true,
- "node": true,
+ "node": true
},
"extends": "eslint:recommended",
"parserOptions": {
"ecmaVersion": 2016,
- "sourceType": "module",
+ "sourceType": "module"
},
"rules": {
"indent": [
diff --git a/runtime/js/core/browser.js b/runtime/js/core/browser.js
index ccbe9f284..dd7856897 100644
--- a/runtime/js/core/browser.js
+++ b/runtime/js/core/browser.js
@@ -26,7 +26,7 @@ export function OpenURL(url) {
* Opens the given filename using the system's default file handler
*
* @export
- * @param {sting} filename
+ * @param {string} filename
* @returns
*/
export function OpenFile(filename) {
diff --git a/runtime/js/core/calls.js b/runtime/js/core/calls.js
index ea3128e8a..9919ff803 100644
--- a/runtime/js/core/calls.js
+++ b/runtime/js/core/calls.js
@@ -62,7 +62,7 @@ if (window.crypto) {
export function Call(bindingName, data, timeout) {
// Timeout infinite by default
- if (timeout == null || timeout == undefined) {
+ if (timeout == null) {
timeout = 0;
}
diff --git a/runtime/js/core/ipc.js b/runtime/js/core/ipc.js
index 1285255a7..b453d3ac7 100644
--- a/runtime/js/core/ipc.js
+++ b/runtime/js/core/ipc.js
@@ -45,7 +45,7 @@ function Invoke(message) {
*
* @export
* @param {string} type
- * @param {string} payload
+ * @param {Object} payload
* @param {string=} callbackID
*/
export function SendMessage(type, payload, callbackID) {
diff --git a/runtime/js/core/main.js b/runtime/js/core/main.js
index 797a8f1c8..51581aadc 100644
--- a/runtime/js/core/main.js
+++ b/runtime/js/core/main.js
@@ -10,11 +10,11 @@ The lightweight framework for web-like apps
/* jshint esversion: 6 */
import * as Log from './log';
import * as Browser from './browser';
-import { On, OnMultiple, Emit, Notify, Heartbeat, Acknowledge } from './events';
-import { NewBinding } from './bindings';
-import { Callback } from './calls';
-import { AddScript, InjectCSS, InjectFirebug } from './utils';
-import { AddIPCListener } from './ipc';
+import {Acknowledge, Emit, Heartbeat, Notify, On, OnMultiple} from './events';
+import {NewBinding} from './bindings';
+import {Callback} from './calls';
+import {AddScript, InjectCSS, InjectFirebug} from './utils';
+import {AddIPCListener} from './ipc';
import * as Store from './store';
// Initialise global if not already
@@ -29,7 +29,7 @@ window.backend = {};
// so we have to use an explicit if statement to prevent webpack from optimizing the code.
if (window.external == undefined) {
window.external = {
- invoke: function(x) {
+ invoke: function (x) {
window.webkit.messageHandlers.external.postMessage(x);
}
};
@@ -75,7 +75,7 @@ window.onerror = function (msg, url, lineNo, columnNo, error) {
};
// Use firebug?
-if( window.usefirebug ) {
+if (window.usefirebug) {
InjectFirebug();
}
diff --git a/runtime/js/runtime/.npmignore b/runtime/js/runtime/.npmignore
index d0a1d1fad..945ce43a9 100644
--- a/runtime/js/runtime/.npmignore
+++ b/runtime/js/runtime/.npmignore
@@ -1 +1 @@
-bridge.js
\ No newline at end of file
+index.js
\ No newline at end of file
diff --git a/runtime/js/runtime/package-lock.json b/runtime/js/runtime/package-lock.json
index 78aef35b7..1efda3274 100644
--- a/runtime/js/runtime/package-lock.json
+++ b/runtime/js/runtime/package-lock.json
@@ -260,9 +260,9 @@
}
},
"path-parse": {
- "version": "1.0.6",
- "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz",
- "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==",
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
+ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
"dev": true
},
"path-type": {
diff --git a/sponsors/bronze sponsor.png b/sponsors/bronze sponsor.png
new file mode 100644
index 000000000..0eeb61e0a
Binary files /dev/null and b/sponsors/bronze sponsor.png differ
diff --git a/v2/NOTES.md b/v2/NOTES.md
new file mode 100644
index 000000000..16bac7122
--- /dev/null
+++ b/v2/NOTES.md
@@ -0,0 +1,40 @@
+
+# Packing linux
+
+ * create app, app.desktop, app.png (512x512)
+ * chmod +x app!
+ * ./linuxdeploy-x86_64.AppImage --appdir AppDir -i react.png -d react.desktop -e react --output appimage
+
+
+# Wails Doctor
+
+Tested on:
+
+ * Debian 8
+ * Ubuntu 20.04
+ * Ubuntu 19.10
+ * Solus 4.1
+ * Centos 8
+ * Gentoo
+ * OpenSUSE/leap
+ * Fedora 31
+
+### Development
+
+Add a new package manager processor here: `v2/internal/system/packagemanager/`. IsAvailable should work even if the package is installed.
+Add your new package manager to the list of package managers in `v2/internal/system/packagemanager/packagemanager.go`:
+
+```
+var db = map[string]PackageManager{
+ "eopkg": NewEopkg(),
+ "apt": NewApt(),
+ "yum": NewYum(),
+ "pacman": NewPacman(),
+ "emerge": NewEmerge(),
+ "zypper": NewZypper(),
+}
+```
+
+## Gentoo
+
+ * Setup docker image using: emerge-webrsync -x -v
diff --git a/v2/README.md b/v2/README.md
new file mode 100644
index 000000000..20ebb18b7
--- /dev/null
+++ b/v2/README.md
@@ -0,0 +1,6 @@
+# Wails v2 ALPHA
+
+This branch contains WORK IN PROGRESS! There are no guarantees. Use at your peril!
+
+This document will be updated as progress is made.
+
diff --git a/v2/cmd/wails/internal/commands/build/README.md b/v2/cmd/wails/internal/commands/build/README.md
new file mode 100644
index 000000000..321445073
--- /dev/null
+++ b/v2/cmd/wails/internal/commands/build/README.md
@@ -0,0 +1,48 @@
+# Build
+
+The build command processes the Wails project and generates an application binary.
+
+## Usage
+
+`wails build `
+
+### Flags
+
+| Flag | Details | Default |
+| :------------- | :----------- | :------ |
+| -clean | Clean the bin directory before building | |
+| -compiler path/to/compiler | Use a different go compiler, eg go1.15beta1 | go |
+| -ldflags "custom ld flags" | Use given ldflags | |
+| -o path/to/binary | Compile to given path/filename | |
+| -k | Keep generated assets | |
+| -package | Create a platform specific package | |
+| -production | Compile in production mode: -ldflags="-w -s" + "-h windows" on Windows | |
+| -tags | Build tags to pass to Go compiler (quoted and space separated) | |
+| -upx | Compress final binary with UPX (if installed) | |
+| -upxflags "custom flags" | Flags to pass to upx | |
+| -v int | Verbosity level (0 - silent, 1 - default, 2 - verbose) | 1 |
+| -delve | If true, runs delve on the compiled binary | false |
+
+## The Build Process
+
+The build process is as follows:
+
+ - The flags are processed, and an Options struct built containing the build context.
+ - The type of target is determined, and a custom build process is followed for target.
+
+### Desktop Target
+
+ - The frontend dependencies are installed. The command is read from the project file `wails.json` under the key `frontend:install` and executed in the `frontend` directory. If this is not defined, it is ignored.
+ - The frontend is then built. This command is read from the project file `wails.json` under the key `frontend:install` and executed in the `frontend` directory. If this is not defined, it is ignored.
+ - The project directory is checked to see if the `build` directory exists. If not, it is created and default project assets are copied to it.
+ - An asset bundle is then created by reading the `html` key from `wails.json` and loading the referenced file. This is then parsed, looking for local Javascript and CSS references. Those files are in turn loaded into memory, converted to C data and saved into the asset bundle located at `build/assets.h`, which also includes the original HTML.
+ - The application icon is then processed: if there is no `build/appicon.png`, a default icon is copied. On Windows, an `app.ico` file is generated from this png. On Mac, `icons.icns` is generated.
+ - If there are icons in the `build/tray` directory, these are processed, converted to C data and saved as `build/trayicons.h`, ready for the compilation step.
+ - If there are icons in the `build/dialog` directory, these are processed, converted to C data and saved as `build/userdialogicons.h`, ready for the compilation step.
+ - If the `-package` flag is given for a Windows target, the Windows assets in the `build/windows` directory are processed: manifest + icons compiled to a `.syso` file (deleted after compilation).
+ - If we are building a universal binary for Mac, the application is compiled for both `arm64` and `amd64`. The `lipo` tool is then executed to create the universal binary.
+ - If we are not building a universal binary for Mac, the application is built using `go build`, using build tags to indicate type of application and build mode (debug/production).
+ - If the `-upx` flag was provided, `upx` is invoked to compress the binary. Custom flags may be provided using the `-upxflags` flag.
+ - If the `package` flag is given for a non Windows target, the application is bundled for the platform. On Mac, this creates a `.app` with the processed icons, the `Info.plist` in `build/darwin` and the compiled binary.
+
+
diff --git a/v2/cmd/wails/internal/commands/build/build.go b/v2/cmd/wails/internal/commands/build/build.go
new file mode 100644
index 000000000..a74ac497b
--- /dev/null
+++ b/v2/cmd/wails/internal/commands/build/build.go
@@ -0,0 +1,230 @@
+package build
+
+import (
+ "fmt"
+ "io"
+ "os"
+ "os/exec"
+ "runtime"
+ "strings"
+ "text/tabwriter"
+ "time"
+
+ "github.com/wailsapp/wails/v2/internal/system"
+
+ "github.com/leaanthony/clir"
+ "github.com/leaanthony/slicer"
+ "github.com/wailsapp/wails/v2/pkg/clilogger"
+ "github.com/wailsapp/wails/v2/pkg/commands/build"
+)
+
+// AddBuildSubcommand adds the `build` command for the Wails application
+func AddBuildSubcommand(app *clir.Cli, w io.Writer) {
+
+ outputType := "desktop"
+
+ validTargetTypes := slicer.String([]string{"desktop", "hybrid", "server"})
+
+ command := app.NewSubCommand("build", "Builds the application")
+
+ // Setup noPackage flag
+ noPackage := false
+ command.BoolFlag("noPackage", "Skips platform specific packaging", &noPackage)
+
+ compilerCommand := "go"
+ command.StringFlag("compiler", "Use a different go compiler to build, eg go1.15beta1", &compilerCommand)
+
+ compress := false
+ command.BoolFlag("upx", "Compress final binary with UPX (if installed)", &compress)
+
+ compressFlags := ""
+ command.StringFlag("upxflags", "Flags to pass to upx", &compressFlags)
+
+ // Setup Platform flag
+ platform := runtime.GOOS
+ //command.StringFlag("platform", "Platform to target", &platform)
+
+ // Verbosity
+ verbosity := 1
+ command.IntFlag("v", "Verbosity level (0 - silent, 1 - default, 2 - verbose)", &verbosity)
+
+ // ldflags to pass to `go`
+ ldflags := ""
+ command.StringFlag("ldflags", "optional ldflags", &ldflags)
+
+ // tags to pass to `go`
+ tags := ""
+ command.StringFlag("tags", "tags to pass to Go compiler (quoted and space separated)", &tags)
+
+ outputFilename := ""
+ command.StringFlag("o", "Output filename", &outputFilename)
+
+ // Clean build directory
+ cleanBuildDirectory := false
+ command.BoolFlag("clean", "Clean the build directory before building", &cleanBuildDirectory)
+
+ webview2 := "download"
+ command.StringFlag("webview2", "WebView2 installer strategy: download,embed,browser,error.", &webview2)
+
+ skipFrontend := false
+ command.BoolFlag("s", "Skips building the frontend", &skipFrontend)
+
+ forceBuild := false
+ command.BoolFlag("f", "Force build application", &forceBuild)
+
+ command.Action(func() error {
+
+ quiet := verbosity == 0
+
+ // Create logger
+ logger := clilogger.New(w)
+ logger.Mute(quiet)
+
+ // Validate output type
+ if !validTargetTypes.Contains(outputType) {
+ return fmt.Errorf("output type '%s' is not valid", outputType)
+ }
+
+ if !quiet {
+ app.PrintBanner()
+ }
+
+ // Check platform
+ validPlatformArch := slicer.String([]string{
+ "darwin",
+ "darwin/amd64",
+ "darwin/arm64",
+ "darwin/universal",
+ "linux",
+ //"linux/amd64",
+ //"linux/arm-7",
+ "windows",
+ "windows/amd64",
+ })
+ if !validPlatformArch.Contains(platform) {
+ return fmt.Errorf("platform %s is not supported", platform)
+ }
+
+ if compress && platform == "darwin/universal" {
+ logger.Println("Warning: compress flag unsupported for universal binaries. Ignoring.")
+ compress = false
+ }
+
+ // Lookup compiler path
+ compilerPath, err := exec.LookPath(compilerCommand)
+ if err != nil {
+ return fmt.Errorf("unable to find compiler: %s", compilerCommand)
+ }
+
+ // Tags
+ experimental := false
+ userTags := []string{}
+ for _, tag := range strings.Split(tags, " ") {
+ thisTag := strings.TrimSpace(tag)
+ if thisTag != "" {
+ userTags = append(userTags, thisTag)
+ }
+ if thisTag == "exp" {
+ experimental = true
+ }
+ }
+
+ if runtime.GOOS == "darwin" && !experimental {
+ return fmt.Errorf("MacOS version coming soon!")
+ }
+
+ // Webview2 installer strategy (download by default)
+ wv2rtstrategy := ""
+ webview2 = strings.ToLower(webview2)
+ if webview2 != "" {
+ validWV2Runtime := slicer.String([]string{"download", "embed", "browser", "error"})
+ if !validWV2Runtime.Contains(webview2) {
+ return fmt.Errorf("invalid option for flag 'webview2': %s", webview2)
+ }
+ // These are the build tags associated with the strategies
+ switch webview2 {
+ case "embed":
+ wv2rtstrategy = "wv2runtime.embed"
+ case "error":
+ wv2rtstrategy = "wv2runtime.error"
+ case "browser":
+ wv2rtstrategy = "wv2runtime.browser"
+ }
+ }
+
+ // Create BuildOptions
+ buildOptions := &build.Options{
+ Logger: logger,
+ OutputType: outputType,
+ OutputFile: outputFilename,
+ CleanBuildDirectory: cleanBuildDirectory,
+ Mode: build.Production,
+ Pack: !noPackage,
+ LDFlags: ldflags,
+ Compiler: compilerCommand,
+ Verbosity: verbosity,
+ ForceBuild: forceBuild,
+ IgnoreFrontend: skipFrontend,
+ Compress: compress,
+ CompressFlags: compressFlags,
+ UserTags: userTags,
+ WebView2Strategy: wv2rtstrategy,
+ }
+
+ // Calculate platform and arch
+ platformSplit := strings.Split(platform, "/")
+ buildOptions.Platform = platformSplit[0]
+ if system.IsAppleSilicon {
+ buildOptions.Arch = "arm64"
+ } else {
+ buildOptions.Arch = runtime.GOARCH
+ }
+ if len(platformSplit) == 2 {
+ buildOptions.Arch = platformSplit[1]
+ }
+
+ // Start a new tabwriter
+ w := new(tabwriter.Writer)
+ w.Init(os.Stdout, 8, 8, 0, '\t', 0)
+
+ // Write out the system information
+ fmt.Fprintf(w, "\n")
+ fmt.Fprintf(w, "App Type: \t%s\n", buildOptions.OutputType)
+ fmt.Fprintf(w, "Platform: \t%s\n", buildOptions.Platform)
+ fmt.Fprintf(w, "Arch: \t%s\n", buildOptions.Arch)
+ fmt.Fprintf(w, "Compiler: \t%s\n", compilerPath)
+ fmt.Fprintf(w, "Skip Frontend: \t%t\n", skipFrontend)
+ fmt.Fprintf(w, "Compress: \t%t\n", buildOptions.Compress)
+ fmt.Fprintf(w, "Package: \t%t\n", buildOptions.Pack)
+ fmt.Fprintf(w, "Clean Build Dir: \t%t\n", buildOptions.CleanBuildDirectory)
+ fmt.Fprintf(w, "LDFlags: \t\"%s\"\n", buildOptions.LDFlags)
+ fmt.Fprintf(w, "Tags: \t[%s]\n", strings.Join(buildOptions.UserTags, ","))
+ if len(buildOptions.OutputFile) > 0 {
+ fmt.Fprintf(w, "Output File: \t%s\n", buildOptions.OutputFile)
+ }
+ fmt.Fprintf(w, "\n")
+ w.Flush()
+
+ return doBuild(buildOptions)
+ })
+}
+
+// doBuild is our main build command
+func doBuild(buildOptions *build.Options) error {
+
+ // Start Time
+ start := time.Now()
+
+ outputFilename, err := build.Build(buildOptions)
+ if err != nil {
+ return err
+ }
+
+ // Output stats
+ elapsed := time.Since(start)
+ buildOptions.Logger.Println("")
+ buildOptions.Logger.Println(fmt.Sprintf("Built '%s' in %s.", outputFilename, elapsed.Round(time.Millisecond).String()))
+ buildOptions.Logger.Println("")
+
+ return nil
+}
diff --git a/v2/cmd/wails/internal/commands/dev/README.md b/v2/cmd/wails/internal/commands/dev/README.md
new file mode 100644
index 000000000..96eb3d2a2
--- /dev/null
+++ b/v2/cmd/wails/internal/commands/dev/README.md
@@ -0,0 +1,22 @@
+# Dev
+
+The dev command allows you to develop your application through a standard browser.
+
+## Usage
+
+`wails dev `
+
+### Flags
+
+| Flag | Details | Default |
+| :------------- | :----------- | :------ |
+| -compiler path/to/compiler | Use a different go compiler, eg go1.15beta1 | go |
+| -ldflags "custom ld flags" | Use given ldflags | |
+| -e list,of,extensions | File extensions to trigger rebuilds | go |
+| -w | Show warnings | false |
+| -v int | Verbosity level (0 - silent, 1 - default, 2 - verbose) | 1 |
+| -loglevel | Loglevel to pass to the application - Trace, Debug, Info, Warning, Error | Debug |
+
+## How it works
+
+The project is built using a special mode that starts a webserver and starts listening to port 34115. When the frontend project is run independently, so long as the JS is wrapped with the runtime method `ready`, then the frontend will connect to the backend code via websockets. The interface should be present in your browser, and you should be able to interact with the backend as you would in a desktop app.
\ No newline at end of file
diff --git a/v2/cmd/wails/internal/commands/dev/dev.go b/v2/cmd/wails/internal/commands/dev/dev.go
new file mode 100644
index 000000000..e9344ea4a
--- /dev/null
+++ b/v2/cmd/wails/internal/commands/dev/dev.go
@@ -0,0 +1,576 @@
+package dev
+
+import (
+ "context"
+ "fmt"
+ "io"
+ "net/http"
+ "os"
+ "os/exec"
+ "os/signal"
+ "path/filepath"
+ "runtime"
+ "strconv"
+ "strings"
+ "sync"
+ "syscall"
+ "time"
+
+ "github.com/wailsapp/wails/v2/cmd/wails/internal"
+ "github.com/wailsapp/wails/v2/internal/gomod"
+
+ "github.com/leaanthony/slicer"
+ "github.com/wailsapp/wails/v2/internal/project"
+
+ "github.com/pkg/browser"
+ "github.com/wailsapp/wails/v2/internal/colour"
+
+ "github.com/fsnotify/fsnotify"
+ "github.com/leaanthony/clir"
+ "github.com/wailsapp/wails/v2/internal/fs"
+ "github.com/wailsapp/wails/v2/internal/process"
+ "github.com/wailsapp/wails/v2/pkg/clilogger"
+ "github.com/wailsapp/wails/v2/pkg/commands/build"
+)
+
+const defaultDevServerURL = "http://localhost:34115"
+
+func LogGreen(message string, args ...interface{}) {
+ text := fmt.Sprintf(message, args...)
+ println(colour.Green(text))
+}
+
+func LogRed(message string, args ...interface{}) {
+ text := fmt.Sprintf(message, args...)
+ println(colour.Red(text))
+}
+
+func LogDarkYellow(message string, args ...interface{}) {
+ text := fmt.Sprintf(message, args...)
+ println(colour.DarkYellow(text))
+}
+
+func sliceToMap(input []string) map[string]struct{} {
+ result := map[string]struct{}{}
+ for _, value := range input {
+ result[value] = struct{}{}
+ }
+ return result
+}
+
+type devFlags struct {
+ ldflags string
+ compilerCommand string
+ assetDir string
+ extensions string
+ openBrowser bool
+ noReload bool
+ wailsjsdir string
+ tags string
+ verbosity int
+ loglevel string
+ forceBuild bool
+ debounceMS int
+ devServerURL string
+}
+
+// AddSubcommand adds the `dev` command for the Wails application
+func AddSubcommand(app *clir.Cli, w io.Writer) error {
+
+ command := app.NewSubCommand("dev", "Development mode")
+
+ flags := defaultDevFlags()
+ command.StringFlag("ldflags", "optional ldflags", &flags.ldflags)
+ command.StringFlag("compiler", "Use a different go compiler to build, eg go1.15beta1", &flags.compilerCommand)
+ command.StringFlag("assetdir", "Serve assets from the given directory", &flags.assetDir)
+ command.StringFlag("e", "Extensions to trigger rebuilds (comma separated) eg go", &flags.extensions)
+ command.BoolFlag("browser", "Open application in browser", &flags.openBrowser)
+ command.BoolFlag("noreload", "Disable reload on asset change", &flags.noReload)
+ command.StringFlag("wailsjsdir", "Directory to generate the Wails JS modules", &flags.wailsjsdir)
+ command.StringFlag("tags", "tags to pass to Go compiler (quoted and space separated)", &flags.tags)
+ command.IntFlag("v", "Verbosity level (0 - silent, 1 - standard, 2 - verbose)", &flags.verbosity)
+ command.StringFlag("loglevel", "Loglevel to use - Trace, Debug, Info, Warning, Error", &flags.loglevel)
+ command.BoolFlag("f", "Force build application", &flags.forceBuild)
+ command.IntFlag("debounce", "The amount of time to wait to trigger a reload on change", &flags.debounceMS)
+ command.StringFlag("devserverurl", "The url of the dev server to use", &flags.devServerURL)
+
+ command.Action(func() error {
+ // Create logger
+ logger := clilogger.New(w)
+ app.PrintBanner()
+
+ experimental := false
+ userTags := []string{}
+ for _, tag := range strings.Split(flags.tags, " ") {
+ thisTag := strings.TrimSpace(tag)
+ if thisTag != "" {
+ userTags = append(userTags, thisTag)
+ }
+ if thisTag == "exp" {
+ experimental = true
+ }
+ }
+
+ if runtime.GOOS == "darwin" && !experimental {
+ return fmt.Errorf("MacOS version coming soon!")
+ }
+
+ cwd, err := os.Getwd()
+ if err != nil {
+ return err
+ }
+
+ projectConfig, err := loadAndMergeProjectConfig(cwd, &flags)
+ if err != nil {
+ return err
+ }
+
+ // Update go.mod to use current wails version
+ err = syncGoModVersion(cwd)
+ if err != nil {
+ return err
+ }
+
+ // Run go mod tidy to ensure we're up to date
+ err = runCommand(cwd, false, "go", "mod", "tidy")
+ if err != nil {
+ return err
+ }
+
+ if flags.tags != "" {
+ err = runCommand(cwd, true, "wails", "generate", "module", "-tags", flags.tags)
+ } else {
+ err = runCommand(cwd, true, "wails", "generate", "module")
+ }
+ if err != nil {
+ return err
+ }
+
+ // frontend:dev server command
+ if projectConfig.DevCommand != "" {
+ var devCommandWaitGroup sync.WaitGroup
+ closer := runFrontendDevCommand(cwd, projectConfig.DevCommand, &devCommandWaitGroup)
+ defer closer(&devCommandWaitGroup)
+ }
+
+ buildOptions := generateBuildOptions(flags)
+ buildOptions.Logger = logger
+ buildOptions.UserTags = internal.ParseUserTags(flags.tags)
+
+ var debugBinaryProcess *process.Process = nil
+
+ // Setup signal handler
+ quitChannel := make(chan os.Signal, 1)
+ signal.Notify(quitChannel, os.Interrupt, os.Kill, syscall.SIGTERM)
+ exitCodeChannel := make(chan int, 1)
+
+ // Do initial build
+ logger.Println("Building application for development...")
+ newProcess, appBinary, err := restartApp(buildOptions, debugBinaryProcess, flags, exitCodeChannel)
+ if err != nil {
+ return err
+ }
+ if newProcess != nil {
+ debugBinaryProcess = newProcess
+ }
+
+ // open browser
+ if flags.openBrowser {
+ url := defaultDevServerURL
+ if flags.devServerURL != "" {
+ url = flags.devServerURL
+ }
+ err = browser.OpenURL(url)
+ if err != nil {
+ return err
+ }
+ }
+
+ // create the project files watcher
+ watcher, err := initialiseWatcher(cwd, logger.Fatal)
+ defer func(watcher *fsnotify.Watcher) {
+ err := watcher.Close()
+ if err != nil {
+ logger.Fatal(err.Error())
+ }
+ }(watcher)
+
+ LogGreen("Watching (sub)/directory: %s", cwd)
+ LogGreen("Using Dev Server URL: %s", flags.devServerURL)
+ LogGreen("Using reload debounce setting of %d milliseconds", flags.debounceMS)
+
+ // Watch for changes and trigger restartApp()
+ doWatcherLoop(buildOptions, debugBinaryProcess, flags, watcher, exitCodeChannel, quitChannel)
+
+ // Kill the current program if running
+ if debugBinaryProcess != nil {
+ err := debugBinaryProcess.Kill()
+ if err != nil {
+ return err
+ }
+ }
+
+ // Remove dev binary
+ err = os.Remove(appBinary)
+ if err != nil {
+ return err
+ }
+
+ LogGreen("Development mode exited")
+
+ return nil
+ })
+ return nil
+}
+
+func syncGoModVersion(cwd string) error {
+ gomodFilename := filepath.Join(cwd, "go.mod")
+ gomodData, err := os.ReadFile(gomodFilename)
+ if err != nil {
+ return err
+ }
+ outOfSync, err := gomod.GoModOutOfSync(gomodData, internal.Version)
+ if err != nil {
+ return err
+ }
+ if !outOfSync {
+ return nil
+ }
+ LogGreen("Updating go.mod to use Wails '%s'", internal.Version)
+ newGoData, err := gomod.UpdateGoModVersion(gomodData, internal.Version)
+ if err != nil {
+ return err
+ }
+ return os.WriteFile(gomodFilename, newGoData, 0755)
+}
+
+func runCommand(dir string, exitOnError bool, command string, args ...string) error {
+ LogGreen("Executing: " + command + " " + strings.Join(args, " "))
+ cmd := exec.Command(command, args...)
+ cmd.Dir = dir
+ output, err := cmd.CombinedOutput()
+ if err != nil {
+ println(string(output))
+ if exitOnError {
+ os.Exit(1)
+ }
+ return err
+ }
+ return nil
+}
+
+// defaultDevFlags generates devFlags with default options
+func defaultDevFlags() devFlags {
+ return devFlags{
+ devServerURL: defaultDevServerURL,
+ compilerCommand: "go",
+ verbosity: 1,
+ extensions: "go",
+ debounceMS: 100,
+ }
+}
+
+// generateBuildOptions creates a build.Options using the flags
+func generateBuildOptions(flags devFlags) *build.Options {
+ result := &build.Options{
+ OutputType: "dev",
+ Mode: build.Dev,
+ Arch: runtime.GOARCH,
+ Pack: false,
+ Platform: runtime.GOOS,
+ LDFlags: flags.ldflags,
+ Compiler: flags.compilerCommand,
+ ForceBuild: flags.forceBuild,
+ IgnoreFrontend: false,
+ Verbosity: flags.verbosity,
+ WailsJSDir: flags.wailsjsdir,
+ }
+ switch runtime.GOOS {
+ case "darwin":
+ result.Pack = false
+ }
+ return result
+}
+
+// loadAndMergeProjectConfig reconciles flags passed to the CLI with project config settings and updates
+// the project config if necessary
+func loadAndMergeProjectConfig(cwd string, flags *devFlags) (*project.Project, error) {
+ projectConfig, err := project.Load(cwd)
+ if err != nil {
+ return nil, err
+ }
+
+ var shouldSaveConfig bool
+
+ if projectConfig.AssetDirectory == "" && flags.assetDir == "" {
+ return nil, fmt.Errorf("No asset directory provided. Please use -assetdir to indicate which directory contains your built assets.")
+ }
+
+ if flags.assetDir == "" && projectConfig.AssetDirectory != "" {
+ flags.assetDir = projectConfig.AssetDirectory
+ }
+
+ if flags.assetDir != projectConfig.AssetDirectory {
+ projectConfig.AssetDirectory = filepath.ToSlash(flags.assetDir)
+ }
+
+ flags.assetDir, err = filepath.Abs(flags.assetDir)
+ if err != nil {
+ return nil, err
+ }
+
+ if flags.devServerURL == defaultDevServerURL && projectConfig.DevServerURL != defaultDevServerURL && projectConfig.DevServerURL != "" {
+ flags.devServerURL = projectConfig.DevServerURL
+ }
+
+ if flags.devServerURL != projectConfig.DevServerURL {
+ projectConfig.DevServerURL = flags.devServerURL
+ shouldSaveConfig = true
+ }
+
+ if flags.wailsjsdir == "" && projectConfig.WailsJSDir != "" {
+ flags.wailsjsdir = projectConfig.WailsJSDir
+ }
+
+ if flags.wailsjsdir == "" {
+ flags.wailsjsdir = "./frontend"
+ }
+
+ if flags.wailsjsdir != projectConfig.WailsJSDir {
+ projectConfig.WailsJSDir = filepath.ToSlash(flags.wailsjsdir)
+ shouldSaveConfig = true
+ }
+
+ if flags.debounceMS == 100 && projectConfig.DebounceMS != 100 {
+ if projectConfig.DebounceMS == 0 {
+ projectConfig.DebounceMS = 100
+ }
+ flags.debounceMS = projectConfig.DebounceMS
+ }
+
+ if flags.debounceMS != projectConfig.DebounceMS {
+ projectConfig.DebounceMS = flags.debounceMS
+ shouldSaveConfig = true
+ }
+
+ if shouldSaveConfig {
+ err = projectConfig.Save()
+ if err != nil {
+ return nil, err
+ }
+ }
+
+ return projectConfig, nil
+}
+
+// runFrontendDevCommand will run the `frontend:dev` command if it was given, ex- `npm run dev`
+func runFrontendDevCommand(cwd string, devCommand string, wg *sync.WaitGroup) func(group *sync.WaitGroup) {
+ LogGreen("Running frontend dev command: '%s'", devCommand)
+ ctx, cancel := context.WithCancel(context.Background())
+ dir := filepath.Join(cwd, "frontend")
+ cmdSlice := strings.Split(devCommand, " ")
+ wg.Add(1)
+ cmd := exec.CommandContext(ctx, cmdSlice[0], cmdSlice[1:]...)
+ cmd.Stderr = os.Stderr
+ cmd.Stdout = os.Stdout
+ cmd.Dir = dir
+ go func(ctx context.Context, devCommand string, cwd string, wg *sync.WaitGroup) {
+ err := cmd.Run()
+ if err != nil {
+ if err.Error() != "exit status 1" {
+ LogRed("Error from '%s': %s", devCommand, err.Error())
+ }
+ }
+ LogGreen("Dev command exited!")
+ wg.Done()
+ }(ctx, devCommand, cwd, wg)
+
+ return func(wg *sync.WaitGroup) {
+ if runtime.GOOS == "windows" {
+ // Credit: https://stackoverflow.com/a/44551450
+ // For whatever reason, killing an npm script on windows just doesn't exit properly with cancel
+ if cmd != nil && cmd.Process != nil {
+ kill := exec.Command("TASKKILL", "/T", "/F", "/PID", strconv.Itoa(cmd.Process.Pid))
+ kill.Stderr = os.Stderr
+ kill.Stdout = os.Stdout
+ err := kill.Run()
+ if err != nil {
+ if err.Error() != "exit status 1" {
+ LogRed("Error from '%s': %s", devCommand, err.Error())
+ }
+ }
+ }
+ } else {
+ cancel()
+ }
+ wg.Wait()
+ }
+}
+
+// initialiseWatcher creates the project directory watcher that will trigger recompile
+func initialiseWatcher(cwd string, logFatal func(string, ...interface{})) (*fsnotify.Watcher, error) {
+ watcher, err := fsnotify.NewWatcher()
+ if err != nil {
+ return nil, err
+ }
+
+ // Get all subdirectories
+ dirs, err := fs.GetSubdirectories(cwd)
+ if err != nil {
+ return nil, err
+ }
+
+ // Setup a watcher for non-node_modules directories
+ dirs.Each(func(dir string) {
+ if strings.Contains(dir, "node_modules") {
+ return
+ }
+ // Ignore build directory
+ if strings.HasPrefix(dir, filepath.Join(cwd, "build")) {
+ return
+ }
+ // Ignore dot directories
+ if strings.HasPrefix(dir, ".") {
+ return
+ }
+ err = watcher.Add(dir)
+ if err != nil {
+ logFatal(err.Error())
+ }
+ })
+ return watcher, nil
+}
+
+// restartApp does the actual rebuilding of the application when files change
+func restartApp(buildOptions *build.Options, debugBinaryProcess *process.Process, flags devFlags, exitCodeChannel chan int) (*process.Process, string, error) {
+
+ appBinary, err := build.Build(buildOptions)
+ println()
+ if err != nil {
+ LogRed("Build error - continuing to run current version")
+ LogDarkYellow(err.Error())
+ return nil, "", nil
+ }
+
+ // Kill existing binary if need be
+ if debugBinaryProcess != nil {
+ killError := debugBinaryProcess.Kill()
+
+ if killError != nil {
+ buildOptions.Logger.Fatal("Unable to kill debug binary (PID: %d)!", debugBinaryProcess.PID())
+ }
+
+ debugBinaryProcess = nil
+ }
+
+ // Start up new binary with correct args
+ args := slicer.StringSlicer{}
+ args.Add("-loglevel", flags.loglevel)
+ if flags.assetDir != "" {
+ args.Add("-assetdir", flags.assetDir)
+ }
+ if flags.devServerURL != "" {
+ args.Add("-devserverurl", flags.devServerURL)
+ }
+ newProcess := process.NewProcess(appBinary, args.AsSlice()...)
+ err = newProcess.Start(exitCodeChannel)
+ if err != nil {
+ // Remove binary
+ if fs.FileExists(appBinary) {
+ deleteError := fs.DeleteFile(appBinary)
+ if deleteError != nil {
+ buildOptions.Logger.Fatal("Unable to delete app binary: " + appBinary)
+ }
+ }
+ buildOptions.Logger.Fatal("Unable to start application: %s", err.Error())
+ }
+
+ return newProcess, appBinary, nil
+}
+
+// doWatcherLoop is the main watch loop that runs while dev is active
+func doWatcherLoop(buildOptions *build.Options, debugBinaryProcess *process.Process, flags devFlags, watcher *fsnotify.Watcher, exitCodeChannel chan int, quitChannel chan os.Signal) {
+ // Main Loop
+ var (
+ err error
+ newBinaryProcess *process.Process
+ )
+ var extensionsThatTriggerARebuild = sliceToMap(strings.Split(flags.extensions, ","))
+ quit := false
+ interval := time.Duration(flags.debounceMS) * time.Millisecond
+ timer := time.NewTimer(interval)
+ rebuild := false
+ reload := false
+ for quit == false {
+ //reload := false
+ select {
+ case exitCode := <-exitCodeChannel:
+ if exitCode == 0 {
+ quit = true
+ }
+ case item := <-watcher.Events:
+ // Check for file writes
+ if item.Op&fsnotify.Write == fsnotify.Write {
+ // Ignore directories
+ if fs.DirExists(item.Name) {
+ continue
+ }
+
+ // Iterate all file patterns
+ ext := filepath.Ext(item.Name)
+ if ext != "" {
+ ext = ext[1:]
+ if _, exists := extensionsThatTriggerARebuild[ext]; exists {
+ rebuild = true
+ timer.Reset(interval)
+ continue
+ }
+ }
+
+ if strings.HasPrefix(item.Name, flags.assetDir) {
+ reload = true
+ }
+ timer.Reset(interval)
+ }
+ // Check for new directories
+ if item.Op&fsnotify.Create == fsnotify.Create {
+ // If this is a folder, add it to our watch list
+ if fs.DirExists(item.Name) {
+ //node_modules is BANNED!
+ if !strings.Contains(item.Name, "node_modules") {
+ err := watcher.Add(item.Name)
+ if err != nil {
+ buildOptions.Logger.Fatal("%s", err.Error())
+ }
+ LogGreen("Added new directory to watcher: %s", item.Name)
+ }
+ }
+ }
+ case <-timer.C:
+ if rebuild {
+ rebuild = false
+ LogGreen("[Rebuild triggered] files updated")
+ // Try and build the app
+ newBinaryProcess, _, err = restartApp(buildOptions, debugBinaryProcess, flags, exitCodeChannel)
+ if err != nil {
+ LogRed("Error during build: %s", err.Error())
+ continue
+ }
+ // If we have a new process, save it
+ if newBinaryProcess != nil {
+ debugBinaryProcess = newBinaryProcess
+ }
+ }
+ if reload {
+ reload = false
+ _, err = http.Get("http://localhost:34115/wails/reload")
+ if err != nil {
+ LogRed("Error during refresh: %s", err.Error())
+ }
+ }
+ case <-quitChannel:
+ LogGreen("\nCaught quit")
+ quit = true
+ }
+ }
+}
diff --git a/v2/cmd/wails/internal/commands/doctor/doctor.go b/v2/cmd/wails/internal/commands/doctor/doctor.go
new file mode 100644
index 000000000..0075a7efb
--- /dev/null
+++ b/v2/cmd/wails/internal/commands/doctor/doctor.go
@@ -0,0 +1,158 @@
+package doctor
+
+import (
+ "fmt"
+ "io"
+ "os"
+ "runtime"
+ "strings"
+ "text/tabwriter"
+
+ "github.com/leaanthony/clir"
+ "github.com/wailsapp/wails/v2/internal/system"
+ "github.com/wailsapp/wails/v2/internal/system/packagemanager"
+ "github.com/wailsapp/wails/v2/pkg/clilogger"
+)
+
+// AddSubcommand adds the `doctor` command for the Wails application
+func AddSubcommand(app *clir.Cli, w io.Writer) error {
+
+ command := app.NewSubCommand("doctor", "Diagnose your environment")
+
+ command.Action(func() error {
+
+ logger := clilogger.New(w)
+
+ app.PrintBanner()
+
+ logger.Print("Scanning system - Please wait (this may take a long time)...")
+
+ // Get system info
+ info, err := system.GetInfo()
+ if err != nil {
+ logger.Println("Failed.")
+ return err
+ }
+ logger.Println("Done.")
+
+ logger.Println("")
+
+ // Start a new tabwriter
+ w := new(tabwriter.Writer)
+ w.Init(os.Stdout, 8, 8, 0, '\t', 0)
+
+ // Write out the system information
+ fmt.Fprintf(w, "System\n")
+ fmt.Fprintf(w, "------\n")
+ fmt.Fprintf(w, "%s\t%s\n", "OS:", info.OS.Name)
+ fmt.Fprintf(w, "%s\t%s\n", "Version: ", info.OS.Version)
+ fmt.Fprintf(w, "%s\t%s\n", "ID:", info.OS.ID)
+
+ // Output Go Information
+ fmt.Fprintf(w, "%s\t%s\n", "Go Version:", runtime.Version())
+ fmt.Fprintf(w, "%s\t%s\n", "Platform:", runtime.GOOS)
+ fmt.Fprintf(w, "%s\t%s\n", "Architecture:", runtime.GOARCH)
+
+ // Exit early if PM not found
+ if info.PM != nil {
+ fmt.Fprintf(w, "%s\t%s\n", "Package Manager: ", info.PM.Name())
+ }
+
+ // Output Dependencies Status
+ var dependenciesMissing = []string{}
+ var externalPackages = []*packagemanager.Dependancy{}
+ var dependenciesAvailableRequired = 0
+ var dependenciesAvailableOptional = 0
+ fmt.Fprintf(w, "\n")
+ fmt.Fprintf(w, "Dependency\tPackage Name\tStatus\tVersion\n")
+ fmt.Fprintf(w, "----------\t------------\t------\t-------\n")
+
+ hasOptionalDependencies := false
+ // Loop over dependencies
+ for _, dependency := range info.Dependencies {
+
+ name := dependency.Name
+ if dependency.Optional {
+ name = "*" + name
+ hasOptionalDependencies = true
+ }
+ packageName := "Unknown"
+ status := "Not Found"
+
+ // If we found the package
+ if dependency.PackageName != "" {
+
+ packageName = dependency.PackageName
+
+ // If it's installed, update the status
+ if dependency.Installed {
+ status = "Installed"
+ } else {
+ // Generate meaningful status text
+ status = "Available"
+
+ if dependency.Optional {
+ dependenciesAvailableOptional++
+ } else {
+ dependenciesAvailableRequired++
+ }
+ }
+ } else {
+ if !dependency.Optional {
+ dependenciesMissing = append(dependenciesMissing, dependency.Name)
+ }
+
+ if dependency.External {
+ externalPackages = append(externalPackages, dependency)
+ }
+ }
+
+ fmt.Fprintf(w, "%s\t%s\t%s\t%s\n", name, packageName, status, dependency.Version)
+ }
+ if hasOptionalDependencies {
+ fmt.Fprintf(w, "\n")
+ fmt.Fprintf(w, "* - Optional Dependency\n")
+ }
+ w.Flush()
+ logger.Println("")
+ logger.Println("Diagnosis")
+ logger.Println("---------")
+
+ // Generate an appropriate diagnosis
+
+ if len(dependenciesMissing) == 0 && dependenciesAvailableRequired == 0 {
+ logger.Println("Your system is ready for Wails development!")
+ } else {
+ logger.Println("Your system has missing dependencies!\n")
+ }
+
+ if dependenciesAvailableRequired != 0 {
+ logger.Println("Required package(s) installation details: \n" + info.Dependencies.InstallAllRequiredCommand())
+ }
+
+ if dependenciesAvailableOptional != 0 {
+ logger.Println("Optional package(s) installation details: \n" + info.Dependencies.InstallAllOptionalCommand())
+ }
+ //
+ //if len(externalPackages) > 0 {
+ // for _, p := range externalPackages {
+ // if p.Optional {
+ // print("[Optional] ")
+ // }
+ // logger.Println("Install " + p.Name + ": " + p.InstallCommand)
+ // }
+ //}
+
+ if len(dependenciesMissing) != 0 {
+ // TODO: Check if apps are available locally and if so, adjust the diagnosis
+ logger.Println("Fatal:")
+ logger.Println("Required dependencies missing: " + strings.Join(dependenciesMissing, " "))
+ logger.Println("Please read this article on how to resolve this: https://wails.app/guides/resolving-missing-packages")
+ }
+
+ logger.Println("")
+ return nil
+ })
+
+ return nil
+}
diff --git a/v2/cmd/wails/internal/commands/generate/README.md b/v2/cmd/wails/internal/commands/generate/README.md
new file mode 100644
index 000000000..c24eb060a
--- /dev/null
+++ b/v2/cmd/wails/internal/commands/generate/README.md
@@ -0,0 +1,18 @@
+# Generate
+
+The `generate` command provides the ability to generate various Wails related components.
+
+## Usage
+
+`wails generate [subcommand] [options]`
+
+## Template
+
+`wails generate template -name [-frontend] [-q]`
+
+Generate a starter template for you to customise.
+
+| Flag | Details |
+| :------------- | :----------- |
+| -frontend | Copies all the files from the current directory into the template's `frontend` directory. Useful for converting frontend projects created by boilerplate generators. |
+| -q | Suppress output |
diff --git a/v2/cmd/wails/internal/commands/generate/generate.go b/v2/cmd/wails/internal/commands/generate/generate.go
new file mode 100644
index 000000000..58f623bf0
--- /dev/null
+++ b/v2/cmd/wails/internal/commands/generate/generate.go
@@ -0,0 +1,23 @@
+package generate
+
+import (
+ "io"
+
+ "github.com/wailsapp/wails/v2/cmd/wails/internal/commands/generate/template"
+
+ "github.com/leaanthony/clir"
+)
+
+// AddSubcommand adds the `generate` command for the Wails application
+func AddSubcommand(app *clir.Cli, w io.Writer) error {
+
+ command := app.NewSubCommand("generate", "Code Generation Tools")
+
+ err := AddModuleCommand(app, command, w)
+ if err != nil {
+ return err
+ }
+ template.AddSubCommand(app, command, w)
+
+ return nil
+}
diff --git a/v2/cmd/wails/internal/commands/generate/module.go b/v2/cmd/wails/internal/commands/generate/module.go
new file mode 100644
index 000000000..91f9309f9
--- /dev/null
+++ b/v2/cmd/wails/internal/commands/generate/module.go
@@ -0,0 +1,58 @@
+package generate
+
+import (
+ "fmt"
+ "github.com/leaanthony/clir"
+ "github.com/wailsapp/wails/v2/cmd/wails/internal"
+ "github.com/wailsapp/wails/v2/internal/shell"
+ "io"
+ "os"
+ "path/filepath"
+ "runtime"
+ "strings"
+)
+
+// AddModuleCommand adds the `module` subcommand for the `generate` command
+func AddModuleCommand(app *clir.Cli, parent *clir.Command, w io.Writer) error {
+
+ command := parent.NewSubCommand("module", "Generate wailsjs modules")
+ var tags string
+ command.StringFlag("tags", "tags to pass to Go compiler (quoted and space separated)", &tags)
+
+ command.Action(func() error {
+
+ filename := "wailsbindings"
+ if runtime.GOOS == "windows" {
+ filename += ".exe"
+ }
+ // go build -tags bindings -o bindings.exe
+ tempDir := os.TempDir()
+ filename = filepath.Join(tempDir, filename)
+
+ cwd, err := os.Getwd()
+ if err != nil {
+ return err
+ }
+
+ tagList := internal.ParseUserTags(tags)
+ tagList = append(tagList, "bindings")
+
+ stdout, stderr, err := shell.RunCommand(cwd, "go", "build", "-tags", strings.Join(tagList, ","), "-o", filename)
+ if err != nil {
+ return fmt.Errorf("%s\n%s\n%s", stdout, stderr, err)
+ }
+
+ stdout, stderr, err = shell.RunCommand(cwd, filename)
+ if err != nil {
+ return fmt.Errorf("%s\n%s\n%s", stdout, stderr, err)
+ }
+
+ err = os.Remove(filename)
+ if err != nil {
+ return err
+ }
+
+ return nil
+ })
+ return nil
+}
diff --git a/v2/cmd/wails/internal/commands/generate/template/base/NEXTSTEPS.md.template b/v2/cmd/wails/internal/commands/generate/template/base/NEXTSTEPS.md.template
new file mode 100644
index 000000000..a357acd82
--- /dev/null
+++ b/v2/cmd/wails/internal/commands/generate/template/base/NEXTSTEPS.md.template
@@ -0,0 +1,42 @@
+# Next Steps
+
+Congratulations on generating your template!
+
+## Completing your template
+
+The next steps to complete the template are:
+
+ 1. Complete the fields in the `template.json` file.
+ - It is really important to ensure `helpurl` is valid as this is where users of the template will be directed for help.
+ 2. Update `README.md`.
+ 3. Edit `wails.json` and ensure all fields are correct, especially:
+ - `assetdir` - path to your assets
+ - `wailsjsdir` - path to generate wailsjs modules
+ - `frontend:install` - The command to install your frontend dependencies
+ - `frontend:build` - The command to build your frontend
+ 4. Remove any `public` or `dist` directories.
+ 5. Delete this file.
+
+## Testing your template
+
+You can test your template by running this command:
+
+`wails init -n test -t {{.TemplateDir}}`
+
+### Checklist
+
+Once generated, do the following tests:
+ - Change into the new project directory and run `wails build`. A working binary should be generated in the `build/bin` project directory.
+ - Run `wails dev`. This will compile your app and run it.
+ - You should be able to see your application running on http://localhost:34115/
+
+## Publishing your template
+
+You can publish a template to a git repository and use it as follows:
+
+`wails init -name test -t https://your/git/url`
+
+EG:
+
+`wails init -name test -t https://github.com/leaanthony/testtemplate`
+
diff --git a/v2/cmd/wails/internal/commands/generate/template/base/README.md b/v2/cmd/wails/internal/commands/generate/template/base/README.md
new file mode 100644
index 000000000..fd993210d
--- /dev/null
+++ b/v2/cmd/wails/internal/commands/generate/template/base/README.md
@@ -0,0 +1,16 @@
+# README
+
+## About
+
+About your template
+
+## Building
+
+To build this project in debug mode, use `wails build`. For production, use `wails build -production`.
+To generate a platform native package, add the `-package` flag.
+
+## Live Development
+
+To run in live development mode, run `wails dev` in the project directory. In another terminal, go into the `frontend`
+directory and run `npm run dev`. The frontend dev server will run on http://localhost:34115. Connect to this
+in your browser and connect to your application.
diff --git a/v2/cmd/wails/internal/commands/generate/template/base/app.tmpl.go b/v2/cmd/wails/internal/commands/generate/template/base/app.tmpl.go
new file mode 100644
index 000000000..dd540dcd2
--- /dev/null
+++ b/v2/cmd/wails/internal/commands/generate/template/base/app.tmpl.go
@@ -0,0 +1,37 @@
+package main
+
+import (
+ "context"
+ "fmt"
+)
+
+// App struct
+type App struct {
+ ctx context.Context
+}
+
+// NewApp creates a new App application struct
+func NewApp() *App {
+ return &App{}
+}
+
+// startup is called at application startup
+func (a *App) startup(ctx context.Context) {
+ // Perform your setup here
+ a.ctx = ctx
+}
+
+// domReady is called after the front-end dom has been loaded
+func (a App) domReady(ctx context.Context) {
+ // Add your action here
+}
+
+// shutdown is called at application termination
+func (a *App) shutdown(ctx context.Context) {
+ // Perform your teardown here
+}
+
+// Greet returns a greeting for the given name
+func (a *App) Greet(name string) string {
+ return fmt.Sprintf("Hello %s!", name)
+}
diff --git a/v2/cmd/wails/internal/commands/generate/template/base/frontend/dist/assets/fonts/OFL.txt b/v2/cmd/wails/internal/commands/generate/template/base/frontend/dist/assets/fonts/OFL.txt
new file mode 100644
index 000000000..9cac04ce8
--- /dev/null
+++ b/v2/cmd/wails/internal/commands/generate/template/base/frontend/dist/assets/fonts/OFL.txt
@@ -0,0 +1,93 @@
+Copyright 2016 The Nunito Project Authors (contact@sansoxygen.com),
+
+This Font Software is licensed under the SIL Open Font License, Version 1.1.
+This license is copied below, and is also available with a FAQ at:
+http://scripts.sil.org/OFL
+
+
+-----------------------------------------------------------
+SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
+-----------------------------------------------------------
+
+PREAMBLE
+The goals of the Open Font License (OFL) are to stimulate worldwide
+development of collaborative font projects, to support the font creation
+efforts of academic and linguistic communities, and to provide a free and
+open framework in which fonts may be shared and improved in partnership
+with others.
+
+The OFL allows the licensed fonts to be used, studied, modified and
+redistributed freely as long as they are not sold by themselves. The
+fonts, including any derivative works, can be bundled, embedded,
+redistributed and/or sold with any software provided that any reserved
+names are not used by derivative works. The fonts and derivatives,
+however, cannot be released under any other type of license. The
+requirement for fonts to remain under this license does not apply
+to any document created using the fonts or their derivatives.
+
+DEFINITIONS
+"Font Software" refers to the set of files released by the Copyright
+Holder(s) under this license and clearly marked as such. This may
+include source files, build scripts and documentation.
+
+"Reserved Font Name" refers to any names specified as such after the
+copyright statement(s).
+
+"Original Version" refers to the collection of Font Software components as
+distributed by the Copyright Holder(s).
+
+"Modified Version" refers to any derivative made by adding to, deleting,
+or substituting -- in part or in whole -- any of the components of the
+Original Version, by changing formats or by porting the Font Software to a
+new environment.
+
+"Author" refers to any designer, engineer, programmer, technical
+writer or other person who contributed to the Font Software.
+
+PERMISSION & CONDITIONS
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of the Font Software, to use, study, copy, merge, embed, modify,
+redistribute, and sell modified and unmodified copies of the Font
+Software, subject to the following conditions:
+
+1) Neither the Font Software nor any of its individual components,
+in Original or Modified Versions, may be sold by itself.
+
+2) Original or Modified Versions of the Font Software may be bundled,
+redistributed and/or sold with any software, provided that each copy
+contains the above copyright notice and this license. These can be
+included either as stand-alone text files, human-readable headers or
+in the appropriate machine-readable metadata fields within text or
+binary files as long as those fields can be easily viewed by the user.
+
+3) No Modified Version of the Font Software may use the Reserved Font
+Name(s) unless explicit written permission is granted by the corresponding
+Copyright Holder. This restriction only applies to the primary font name as
+presented to the users.
+
+4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
+Software shall not be used to promote, endorse or advertise any
+Modified Version, except to acknowledge the contribution(s) of the
+Copyright Holder(s) and the Author(s) or with their explicit written
+permission.
+
+5) The Font Software, modified or unmodified, in part or in whole,
+must be distributed entirely under this license, and must not be
+distributed under any other license. The requirement for fonts to
+remain under this license does not apply to any document created
+using the Font Software.
+
+TERMINATION
+This license becomes null and void if any of the above conditions are
+not met.
+
+DISCLAIMER
+THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
+COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
+DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
+OTHER DEALINGS IN THE FONT SOFTWARE.
diff --git a/v2/cmd/wails/internal/commands/generate/template/base/frontend/dist/assets/fonts/nunito-v16-latin-regular.woff2 b/v2/cmd/wails/internal/commands/generate/template/base/frontend/dist/assets/fonts/nunito-v16-latin-regular.woff2
new file mode 100644
index 000000000..2f9cc5964
Binary files /dev/null and b/v2/cmd/wails/internal/commands/generate/template/base/frontend/dist/assets/fonts/nunito-v16-latin-regular.woff2 differ
diff --git a/v2/cmd/wails/internal/commands/generate/template/base/frontend/dist/assets/images/logo-dark.svg b/v2/cmd/wails/internal/commands/generate/template/base/frontend/dist/assets/images/logo-dark.svg
new file mode 100644
index 000000000..855d7e0ef
--- /dev/null
+++ b/v2/cmd/wails/internal/commands/generate/template/base/frontend/dist/assets/images/logo-dark.svg
@@ -0,0 +1,80 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/v2/cmd/wails/internal/commands/generate/template/base/frontend/dist/index.html b/v2/cmd/wails/internal/commands/generate/template/base/frontend/dist/index.html
new file mode 100644
index 000000000..7f516f7fa
--- /dev/null
+++ b/v2/cmd/wails/internal/commands/generate/template/base/frontend/dist/index.html
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+ Please enter your name below 👇
+
+
+ Greet
+
+
+
+
+
+
\ No newline at end of file
diff --git a/v2/cmd/wails/internal/commands/generate/template/base/frontend/dist/main.css b/v2/cmd/wails/internal/commands/generate/template/base/frontend/dist/main.css
new file mode 100644
index 000000000..af6412466
--- /dev/null
+++ b/v2/cmd/wails/internal/commands/generate/template/base/frontend/dist/main.css
@@ -0,0 +1,72 @@
+html {
+ background-color: rgba(33, 37, 43, 1);
+ text-align: center;
+ color: white;
+}
+
+body {
+ margin: 0;
+ color: white;
+ font-family: "Nunito", -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto",
+ "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue",
+ sans-serif;
+}
+
+@font-face {
+ font-family: "Nunito";
+ font-style: normal;
+ font-weight: 400;
+ src: local(""),
+ url("assets/fonts/nunito-v16-latin-regular.woff2") format("woff2");
+}
+
+.logo {
+ display: block;
+ width: 35%;
+ height: 35%;
+ margin: auto;
+ padding: 15% 0 0;
+ background-position: center;
+ background-repeat: no-repeat;
+ background-image: url("./assets/images/logo-dark.svg");
+}
+.result {
+ height: 20px;
+ line-height: 20px;
+ margin: 1.5rem auto;
+}
+.input-box .btn {
+ width: 60px;
+ height: 30px;
+ line-height: 30px;
+ border-radius: 3px;
+ border: none;
+ margin: 0 0 0 20px;
+ padding: 0 8px;
+ cursor: pointer;
+}
+.input-box .btn:hover {
+ background-image: linear-gradient(to top, #cfd9df 0%, #e2ebf0 100%);
+ color: #333333;
+}
+
+.input-box .input {
+ border: none;
+ border-radius: 3px;
+ outline: none;
+ height: 30px;
+ line-height: 30px;
+ padding: 0 10px;
+ background-color: rgba(240, 240, 240, 1);
+ -webkit-font-smoothing: antialiased;
+}
+
+.input-box .input:hover {
+ border: none;
+ background-color: rgba(255, 255, 255, 1);
+}
+
+.input-box .input:focus {
+ border: none;
+ background-color: rgba(255, 255, 255, 1);
+}
diff --git a/v2/cmd/wails/internal/commands/generate/template/base/frontend/dist/main.js b/v2/cmd/wails/internal/commands/generate/template/base/frontend/dist/main.js
new file mode 100644
index 000000000..db404e459
--- /dev/null
+++ b/v2/cmd/wails/internal/commands/generate/template/base/frontend/dist/main.js
@@ -0,0 +1,23 @@
+// Get input + focus
+let nameElement = document.getElementById("name");
+nameElement.focus();
+
+// Setup the greet function
+window.greet = function () {
+
+ // Get name
+ let name = nameElement.value;
+
+ // Call App.Greet(name)
+ window.go.main.App.Greet(name).then((result) => {
+ // Update result with data back from App.Greet()
+ document.getElementById("result").innerText = result;
+ });
+};
+
+nameElement.onkeydown = function (e) {
+ console.log(e)
+ if (e.keyCode == 13) {
+ window.greet()
+ }
+}
\ No newline at end of file
diff --git a/v2/cmd/wails/internal/commands/generate/template/base/frontend/package.tmpl.json b/v2/cmd/wails/internal/commands/generate/template/base/frontend/package.tmpl.json
new file mode 100644
index 000000000..01780288d
--- /dev/null
+++ b/v2/cmd/wails/internal/commands/generate/template/base/frontend/package.tmpl.json
@@ -0,0 +1,12 @@
+{
+ "name": "{{.ProjectName}}",
+ "version": "1.0.0",
+ "description": "",
+ "main": "",
+ "scripts": {
+ "test": "echo \"Error: no test specified\" && exit 1",
+ "build": ""
+ },
+ "keywords": [],
+ "author": "{{.AuthorName}}"
+}
diff --git a/v2/cmd/wails/internal/commands/generate/template/base/go.mod.tmpl b/v2/cmd/wails/internal/commands/generate/template/base/go.mod.tmpl
new file mode 100644
index 000000000..166b9252d
--- /dev/null
+++ b/v2/cmd/wails/internal/commands/generate/template/base/go.mod.tmpl
@@ -0,0 +1,38 @@
+module changeme
+
+go 1.17
+
+require github.com/wailsapp/wails/v2 {{.WailsVersion}}
+
+require (
+github.com/andybalholm/brotli v1.0.2 // indirect
+github.com/davecgh/go-spew v1.1.1 // indirect
+github.com/fasthttp/websocket v0.0.0-20200320073529-1554a54587ab // indirect
+github.com/gabriel-vasile/mimetype v1.3.1 // indirect
+github.com/go-ole/go-ole v1.2.5 // indirect
+github.com/gofiber/fiber/v2 v2.17.0 // indirect
+github.com/gofiber/websocket/v2 v2.0.8 // indirect
+github.com/google/uuid v1.1.2 // indirect
+github.com/imdario/mergo v0.3.12 // indirect
+github.com/jchv/go-winloader v0.0.0-20200815041850-dec1ee9a7fd5 // indirect
+github.com/klauspost/compress v1.12.2 // indirect
+github.com/leaanthony/debme v1.2.1 // indirect
+github.com/leaanthony/go-ansi-parser v1.0.1 // indirect
+github.com/leaanthony/go-common-file-dialog v1.0.3 // indirect
+github.com/leaanthony/go-webview2 v0.0.0-20210914103035-f00aa774a934 // indirect
+github.com/leaanthony/slicer v1.5.0 // indirect
+github.com/leaanthony/typescriptify-golang-structs v0.1.7 // indirect
+github.com/leaanthony/webview2runtime v1.1.0 // indirect
+github.com/leaanthony/winc v0.0.0-20210921073452-54963136bf18 // indirect
+github.com/pkg/browser v0.0.0-20210706143420-7d21f8c997e2 // indirect
+github.com/pkg/errors v0.9.1 // indirect
+github.com/savsgio/gotils v0.0.0-20200117113501-90175b0fbe3f // indirect
+github.com/tkrajina/go-reflector v0.5.5 // indirect
+github.com/valyala/bytebufferpool v1.0.0 // indirect
+github.com/valyala/fasthttp v1.28.0 // indirect
+github.com/valyala/tcplisten v1.0.0 // indirect
+golang.org/x/net v0.0.0-20210510120150-4163338589ed // indirect
+golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf // indirect
+)
+
+// replace github.com/wailsapp/wails/v2 {{.WailsVersion}} => {{.WailsDirectory}}
\ No newline at end of file
diff --git a/v2/cmd/wails/internal/commands/generate/template/base/go.sum b/v2/cmd/wails/internal/commands/generate/template/base/go.sum
new file mode 100644
index 000000000..8e8bd03fd
--- /dev/null
+++ b/v2/cmd/wails/internal/commands/generate/template/base/go.sum
@@ -0,0 +1,225 @@
+github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y=
+github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA=
+github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0=
+github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs=
+github.com/andybalholm/brotli v1.0.2 h1:JKnhI/XQ75uFBTiuzXpzFrUriDPiZjlOSzh6wXogP0E=
+github.com/andybalholm/brotli v1.0.2/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y=
+github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
+github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
+github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
+github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
+github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o=
+github.com/fasthttp/websocket v0.0.0-20200320073529-1554a54587ab h1:9e2joQGp642wHGFP5m86SDptAavrdGBe8/x9DGEEAaI=
+github.com/fasthttp/websocket v0.0.0-20200320073529-1554a54587ab/go.mod h1:smsv/h4PBEBaU0XDTY5UwJTpZv69fQ0FfcLJr21mA6Y=
+github.com/fatih/structtag v1.2.0/go.mod h1:mBJUNpUnHmRKrKlQQlmCrh5PuhftFbNv8Ys4/aAZl94=
+github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
+github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
+github.com/gabriel-vasile/mimetype v1.3.1 h1:qevA6c2MtE1RorlScnixeG0VA1H4xrXyhyX3oWBynNQ=
+github.com/gabriel-vasile/mimetype v1.3.1/go.mod h1:fA8fi6KUiG7MgQQ+mEWotXoEOvmxRtOJlERCzSmRvr8=
+github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
+github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M=
+github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
+github.com/go-git/gcfg v1.5.0/go.mod h1:5m20vg6GwYabIxaOonVkTdrILxQMpEShl1xiMF4ua+E=
+github.com/go-git/go-billy/v5 v5.0.0/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0=
+github.com/go-git/go-billy/v5 v5.1.0/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0=
+github.com/go-git/go-billy/v5 v5.2.0/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0=
+github.com/go-git/go-git-fixtures/v4 v4.0.2-0.20200613231340-f56387b50c12/go.mod h1:m+ICp2rF3jDhFgEZ/8yziagdT1C+ZpZcrJjappBCDSw=
+github.com/go-git/go-git/v5 v5.3.0/go.mod h1:xdX4bWJ48aOrdhnl2XqHYstHbbp6+LFS4r4X+lNVprw=
+github.com/go-ole/go-ole v1.2.4/go.mod h1:XCwSNxSkXRo4vlyPy93sltvi/qJq0jqQhjqQNIwKuxM=
+github.com/go-ole/go-ole v1.2.5 h1:t4MGB5xEDZvXI+0rMjjsfBsD7yAgp/s9ZDkL1JndXwY=
+github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
+github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
+github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
+github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
+github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI=
+github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo=
+github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw=
+github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM=
+github.com/gofiber/fiber/v2 v2.17.0 h1:qP3PkGUbBB0i9iQh5E057XI1yO5CZigUxZhyUFYAFoM=
+github.com/gofiber/fiber/v2 v2.17.0/go.mod h1:iftruuHGkRYGEXVISmdD7HTYWyfS2Bh+Dkfq4n/1Owg=
+github.com/gofiber/websocket/v2 v2.0.8 h1:Hb4y6IxYZVMO0segROODXJiXVgVD3a6i7wnfot8kM6k=
+github.com/gofiber/websocket/v2 v2.0.8/go.mod h1:fv8HSGQX09sauNv9g5Xq8GeGAaahLFYQKKb4ZdT0x2w=
+github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
+github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
+github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
+github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
+github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
+github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
+github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
+github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y=
+github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
+github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU=
+github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
+github.com/jackmordaunt/icns v1.0.0/go.mod h1:7TTQVEuGzVVfOPPlLNHJIkzA6CoV7aH1Dv9dW351oOo=
+github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
+github.com/jchv/go-winloader v0.0.0-20200815041850-dec1ee9a7fd5 h1:pdFFlHXY9tZXmJz+tRSm1DzYEH4ebha7cffmm607bMU=
+github.com/jchv/go-winloader v0.0.0-20200815041850-dec1ee9a7fd5/go.mod h1:alcuEEnZsY1WQsagKhZDsoPCRoOijYqhZvPwLG0kzVs=
+github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4=
+github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
+github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
+github.com/klauspost/compress v1.8.2/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
+github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
+github.com/klauspost/compress v1.12.2 h1:2KCfW3I9M7nSc5wOqXAlW2v2U6v+w6cbjvbfp+OykW8=
+github.com/klauspost/compress v1.12.2/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg=
+github.com/klauspost/cpuid v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
+github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
+github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
+github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
+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.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
+github.com/leaanthony/clir v1.0.4/go.mod h1:k/RBkdkFl18xkkACMCLt09bhiZnrGORoxmomeMvDpE0=
+github.com/leaanthony/debme v1.1.1/go.mod h1:3V+sCm5tYAgQymvSOfYQ5Xx2JCr+OXiD9Jkw3otUjiA=
+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/go-ansi-parser v1.0.1 h1:97v6c5kYppVsbScf4r/VZdXyQ21KQIfeQOk2DgKxGG4=
+github.com/leaanthony/go-ansi-parser v1.0.1/go.mod h1:7arTzgVI47srICYhvgUV4CGd063sGEeoSlych5yeSPM=
+github.com/leaanthony/go-common-file-dialog v1.0.3 h1:O0uGjKnWtdEADGrkg+TyAAbZylykMwwx/MNEXn9fp+Y=
+github.com/leaanthony/go-common-file-dialog v1.0.3/go.mod h1:TGhEc9eSJgRsupZ+iH1ZgAOnEo9zp05cRH2j08RPrF0=
+github.com/leaanthony/go-webview2 v0.0.0-20210914103035-f00aa774a934 h1:nK/JTPyJi5QRqYjVZjXgtN4/dhg2qtngoLxLDVn429k=
+github.com/leaanthony/go-webview2 v0.0.0-20210914103035-f00aa774a934/go.mod h1:lS5ds4bruPk9d7lzdF/OH31Z0YCerI6MmHNFGsWoUnM=
+github.com/leaanthony/gosod v1.0.2/go.mod h1:W8RyeSFBXu7RpIxPGEJfW4moSyGGEjlJMLV25wEbAdU=
+github.com/leaanthony/idgen v1.0.0/go.mod h1:4nBZnt8ml/f/ic/EVQuLxuj817RccT2fyrUaZFxrcVA=
+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/typescriptify-golang-structs v0.1.7 h1:yoznzWzyxkO/iWdlpq+aPcuJ5Y/hpjq/lmgMFmpjwl0=
+github.com/leaanthony/typescriptify-golang-structs v0.1.7/go.mod h1:cWtOkiVhMF77e6phAXUcfNwYmMwCJ67Sij24lfvi9Js=
+github.com/leaanthony/webview2runtime v1.1.0 h1:N0pv55ift8XtqozIp4PNOtRCJ/Qdd/qzx80lUpalS4c=
+github.com/leaanthony/webview2runtime v1.1.0/go.mod h1:hH9GnWCve3DYzNaPOcPbhHQ7fodXR1QJNsnwixid4Tk=
+github.com/leaanthony/winc v0.0.0-20210921073452-54963136bf18 h1:5iOd93PZbpH4Iir8QkC4coFD+zEQEZSIRcjwjTFZkr0=
+github.com/leaanthony/winc v0.0.0-20210921073452-54963136bf18/go.mod h1:KEbMsKoznsebyGHwLk5LqkFOxL5uXSRdvpP4+avmAMs=
+github.com/leaanthony/winicon v1.0.0/go.mod h1:en5xhijl92aphrJdmRPlh4NI1L6wq3gEm0LpXAPghjU=
+github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
+github.com/logrusorgru/aurora v0.0.0-20181002194514-a7b3b318ed4e/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4=
+github.com/matryer/is v1.4.0 h1:sosSmIWwkYITGrxZ25ULNDeKiMNzFSr4V/eqBQP0PeE=
+github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU=
+github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
+github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
+github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
+github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
+github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
+github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8=
+github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
+github.com/olekukonko/tablewriter v0.0.4/go.mod h1:zq6QwlOf5SlnkVbMSr5EoBv3636FWnp+qbPhuoO21uA=
+github.com/pkg/browser v0.0.0-20210706143420-7d21f8c997e2 h1:acNfDZXmm28D2Yg/c3ALnZStzNaZMSagpbr96vY6Zjc=
+github.com/pkg/browser v0.0.0-20210706143420-7d21f8c997e2/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI=
+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/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/savsgio/gotils v0.0.0-20200117113501-90175b0fbe3f h1:PgA+Olipyj258EIEYnpFFONrrCcAIWNUNoFhUfMqAGY=
+github.com/savsgio/gotils v0.0.0-20200117113501-90175b0fbe3f/go.mod h1:lHhJedqxCoHN+zMtwGNTXWmF0u9Jt363FYRhV6g0CdY=
+github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
+github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
+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/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
+github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
+github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
+github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
+github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/tc-hib/winres v0.1.5/go.mod h1:pe6dOR40VOrGz8PkzreVKNvEKnlE8t4yR8A8naL+t7A=
+github.com/tdewolff/minify v2.3.6+incompatible/go.mod h1:9Ov578KJUmAWpS6NeZwRZyT56Uf6o3Mcz9CEsg8USYs=
+github.com/tdewolff/parse v2.3.4+incompatible/go.mod h1:8oBwCsVmUkgHO8M5iCzSIDtpzXOT0WXX9cWhz+bIzJQ=
+github.com/tdewolff/test v1.0.6/go.mod h1:6DAvZliBAAnD7rhVgwaM7DE5/d9NMOAJ09SqYqeK4QE=
+github.com/tidwall/gjson v1.8.0/go.mod h1:5/xDoumyyDNerp2U36lyolv46b3uF/9Bu6OfyQ9GImk=
+github.com/tidwall/match v1.0.3/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
+github.com/tidwall/pretty v1.1.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
+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.5/go.mod h1:ECbqLgccecY5kPmPmXg1MrHW585yMcDkVl6IvJe64T4=
+github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
+github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
+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/fasthttp v1.9.0/go.mod h1:FstJa9V+Pj9vQ7OJie2qMHdwemEDaDiSdBnvPM1Su9w=
+github.com/valyala/fasthttp v1.26.0/go.mod h1:cmWIqlu99AO/RKcp1HWaViTqc57FswJOfYYdPJBl8BA=
+github.com/valyala/fasthttp v1.28.0 h1:ruVmTmZaBR5i67NqnjvvH5gEv0zwHfWtbjoyW98iho4=
+github.com/valyala/fasthttp v1.28.0/go.mod h1:cmWIqlu99AO/RKcp1HWaViTqc57FswJOfYYdPJBl8BA=
+github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio=
+github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8=
+github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc=
+github.com/wzshiming/ctc v1.2.3/go.mod h1:2tVAtIY7SUyraSk0JxvwmONNPFL4ARavPuEsg5+KA28=
+github.com/wzshiming/winseq v0.0.0-20200112104235-db357dc107ae/go.mod h1:VTAq37rkGeV+WOybvZwjXiJOicICdpLCN8ifpISjK20=
+github.com/xanzy/ssh-agent v0.3.0/go.mod h1:3s9xbODqPuuhK9JV1R321M/FlMZSBvE5aY6eAcqrDh0=
+github.com/xyproto/xpm v1.2.1/go.mod h1:cMnesLsD0PBXLgjDfTDEaKr8XyTFsnP1QycSqRw7BiY=
+github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
+github.com/ztrue/tracerr v0.3.0/go.mod h1:qEalzze4VN9O8tnhBXScfCrmoJo10o8TN5ciKjm6Mww=
+golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
+golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
+golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
+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/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
+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-20210505024714-0287a6fb4125/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
+golang.org/x/net v0.0.0-20210510120150-4163338589ed h1:p9UgmWI9wKpfYmgaV/IZKGdXc5qEK45tDwwwDyjS26I=
+golang.org/x/net v0.0.0-20210510120150-4163338589ed/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
+golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+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-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200107162124-548cf772de50/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200810151505-1b9f1253b3ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20210611083646-a4fc73990273/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf h1:2ucpDCmfkl8Bd/FsLtiD653Wf96cW37s+iGx93zsu4k=
+golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
+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/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
+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.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
+golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/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=
+google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
+google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
+gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
+gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
+gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
+gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+nhooyr.io/websocket v1.8.6/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0=
diff --git a/v2/cmd/wails/internal/commands/generate/template/base/main.tmpl.go b/v2/cmd/wails/internal/commands/generate/template/base/main.tmpl.go
new file mode 100644
index 000000000..4bec207bd
--- /dev/null
+++ b/v2/cmd/wails/internal/commands/generate/template/base/main.tmpl.go
@@ -0,0 +1,54 @@
+package main
+
+import (
+ "embed"
+ "log"
+
+ "github.com/wailsapp/wails/v2"
+ "github.com/wailsapp/wails/v2/pkg/logger"
+ "github.com/wailsapp/wails/v2/pkg/options"
+ "github.com/wailsapp/wails/v2/pkg/options/windows"
+)
+
+//go:embed frontend/dist
+var assets embed.FS
+
+func main() {
+ // Create an instance of the app structure
+ app := NewApp()
+
+ // Create application with options
+ err := wails.Run(&options.App{
+ Title: "{{.ProjectName}}",
+ Width: 1024,
+ Height: 768,
+ // MinWidth: 720,
+ // MinHeight: 570,
+ // MaxWidth: 1280,
+ // MaxHeight: 740,
+ DisableResize: false,
+ Fullscreen: false,
+ Frameless: false,
+ StartHidden: false,
+ HideWindowOnClose: false,
+ RGBA: &options.RGBA{255, 255, 255, 255},
+ Assets: assets,
+ LogLevel: logger.DEBUG,
+ OnStartup: app.startup,
+ OnDomReady: app.domReady,
+ OnShutdown: app.shutdown,
+ Bind: []interface{}{
+ app,
+ },
+ // Windows platform specific options
+ Windows: &windows.Options{
+ WebviewIsTransparent: false,
+ WindowIsTranslucent: false,
+ DisableWindowIcon: false,
+ },
+ })
+
+ if err != nil {
+ log.Fatal(err)
+ }
+}
diff --git a/v2/cmd/wails/internal/commands/generate/template/base/template.template.json b/v2/cmd/wails/internal/commands/generate/template/base/template.template.json
new file mode 100644
index 000000000..bde089e00
--- /dev/null
+++ b/v2/cmd/wails/internal/commands/generate/template/base/template.template.json
@@ -0,0 +1,7 @@
+{
+ "name": "Long name",
+ "shortname": "{{.Name}}",
+ "author": "",
+ "description": "Description of the template",
+ "helpurl": "URL for help with the template, eg homepage"
+}
\ No newline at end of file
diff --git a/v2/cmd/wails/internal/commands/generate/template/base/wails.tmpl.json b/v2/cmd/wails/internal/commands/generate/template/base/wails.tmpl.json
new file mode 100644
index 000000000..b8d08108d
--- /dev/null
+++ b/v2/cmd/wails/internal/commands/generate/template/base/wails.tmpl.json
@@ -0,0 +1,11 @@
+{
+ "name": "{{.ProjectName}}",
+ "outputfilename": "{{.BinaryName}}",
+ "assetdir": "frontend/dist",
+ "frontend:install": "npm install",
+ "frontend:build": "npm run build",
+ "author": {
+ "name": "{{.AuthorName}}",
+ "email": "{{.AuthorEmail}}"
+ }
+}
diff --git a/v2/cmd/wails/internal/commands/generate/template/template.go b/v2/cmd/wails/internal/commands/generate/template/template.go
new file mode 100644
index 000000000..6464ff7c4
--- /dev/null
+++ b/v2/cmd/wails/internal/commands/generate/template/template.go
@@ -0,0 +1,215 @@
+package template
+
+import (
+ "embed"
+ "fmt"
+ "io"
+ "os"
+ "path/filepath"
+
+ "github.com/leaanthony/debme"
+
+ "github.com/leaanthony/gosod"
+ "github.com/wailsapp/wails/v2/internal/fs"
+
+ "github.com/leaanthony/clir"
+ "github.com/tidwall/sjson"
+)
+
+//go:embed base
+var base embed.FS
+
+func AddSubCommand(app *clir.Cli, parent *clir.Command, w io.Writer) {
+
+ // command
+ command := parent.NewSubCommand("template", "Generates a wails template")
+
+ name := ""
+ command.StringFlag("name", "The name of the template", &name)
+
+ existingProjectDir := ""
+ command.StringFlag("frontend", "A path to an existing frontend project to include in the template", &existingProjectDir)
+
+ // Quiet Init
+ quiet := false
+ command.BoolFlag("q", "Suppress output to console", &quiet)
+
+ command.Action(func() error {
+
+ // name is mandatory
+ if name == "" {
+ command.PrintHelp()
+ return fmt.Errorf("no template name given")
+ }
+
+ // If the current directory is not empty, we create a new directory
+ cwd, err := os.Getwd()
+ if err != nil {
+ return err
+ }
+ templateDir := filepath.Join(cwd, name)
+ if !fs.DirExists(templateDir) {
+ err := os.MkdirAll(templateDir, 0755)
+ if err != nil {
+ return err
+ }
+ }
+ empty, err := fs.DirIsEmpty(templateDir)
+ if err != nil {
+ return err
+ }
+ if !empty {
+ templateDir = filepath.Join(cwd, name)
+ println("Creating new template directory:", name)
+ err = fs.Mkdir(templateDir)
+ if err != nil {
+ return err
+ }
+ }
+
+ // Create base template
+ baseTemplate, err := debme.FS(base, "base")
+ if err != nil {
+ return err
+ }
+ g := gosod.New(baseTemplate)
+ g.SetTemplateFilters([]string{".template"})
+
+ err = os.Chdir(templateDir)
+ if err != nil {
+ return err
+ }
+
+ type templateData struct {
+ Name string
+ Description string
+ TemplateDir string
+ WailsVersion string
+ }
+
+ println("Extracting base template files...")
+
+ err = g.Extract(templateDir, &templateData{
+ Name: name,
+ TemplateDir: templateDir,
+ WailsVersion: app.Version(),
+ })
+ if err != nil {
+ return err
+ }
+
+ err = os.Chdir(cwd)
+ if err != nil {
+ return err
+ }
+
+ // If we aren't migrating the files, just exit
+ if existingProjectDir == "" {
+ return nil
+ }
+
+ // Remove frontend directory
+ frontendDir := filepath.Join(templateDir, "frontend")
+ err = os.RemoveAll(frontendDir)
+ if err != nil {
+ return err
+ }
+
+ // Copy the files into a new frontend directory
+ println("Migrating existing project files to frontend directory...")
+
+ sourceDir, err := filepath.Abs(existingProjectDir)
+ if err != nil {
+ return err
+ }
+
+ newFrontendDir := filepath.Join(templateDir, "frontend")
+ err = fs.CopyDirExtended(sourceDir, newFrontendDir, []string{name, "node_modules"})
+ if err != nil {
+ return err
+ }
+
+ // Process package.json
+ err = processPackageJSON(frontendDir)
+ if err != nil {
+ return err
+ }
+
+ // Process package-lock.json
+ err = processPackageLockJSON(frontendDir)
+ if err != nil {
+ return err
+ }
+
+ // Remove node_modules - ignore error, eg it doesn't exist
+ _ = os.RemoveAll(filepath.Join(frontendDir, "node_modules"))
+
+ return nil
+
+ })
+}
+
+func processPackageJSON(frontendDir string) error {
+ var err error
+
+ packageJSON := filepath.Join(frontendDir, "package.json")
+ if !fs.FileExists(packageJSON) {
+ println("No package.json found - cannot process.")
+ return nil
+ }
+
+ data, err := os.ReadFile(packageJSON)
+ if err != nil {
+ return err
+ }
+ json := string(data)
+
+ // We will ignore these errors - it's not critical
+ println("Updating package.json data...")
+ json, _ = sjson.Set(json, "name", "{{.ProjectName}}")
+ json, _ = sjson.Set(json, "author", "{{.AuthorName}}")
+
+ err = os.WriteFile(packageJSON, []byte(json), 0644)
+ if err != nil {
+ return err
+ }
+ baseDir := filepath.Dir(packageJSON)
+ println("Renaming package.json -> package.tmpl.json...")
+ err = os.Rename(packageJSON, filepath.Join(baseDir, "package.tmpl.json"))
+ if err != nil {
+ return err
+ }
+ return nil
+}
+
+func processPackageLockJSON(frontendDir string) error {
+ var err error
+
+ filename := filepath.Join(frontendDir, "package-lock.json")
+ if !fs.FileExists(filename) {
+ println("No package-lock.json found - cannot process.")
+ return nil
+ }
+
+ data, err := os.ReadFile(filename)
+ if err != nil {
+ return err
+ }
+ json := string(data)
+
+ // We will ignore these errors - it's not critical
+ println("Updating package-lock.json data...")
+ json, _ = sjson.Set(json, "name", "{{.ProjectName}}")
+
+ err = os.WriteFile(filename, []byte(json), 0644)
+ if err != nil {
+ return err
+ }
+ baseDir := filepath.Dir(filename)
+ println("Renaming package-lock.json -> package-lock.tmpl.json...")
+ err = os.Rename(filename, filepath.Join(baseDir, "package-lock.tmpl.json"))
+ if err != nil {
+ return err
+ }
+ return nil
+}
diff --git a/v2/cmd/wails/internal/commands/initialise/initialise.go b/v2/cmd/wails/internal/commands/initialise/initialise.go
new file mode 100644
index 000000000..f87e6b7a3
--- /dev/null
+++ b/v2/cmd/wails/internal/commands/initialise/initialise.go
@@ -0,0 +1,235 @@
+package initialise
+
+import (
+ "fmt"
+ "github.com/flytam/filenamify"
+ "github.com/leaanthony/slicer"
+ "io"
+ "os"
+ "os/exec"
+ "path/filepath"
+ "strings"
+ "time"
+
+ "github.com/wailsapp/wails/v2/pkg/buildassets"
+
+ "github.com/wailsapp/wails/v2/cmd/wails/internal/commands/initialise/templates"
+
+ "github.com/leaanthony/clir"
+ "github.com/pkg/errors"
+ "github.com/wailsapp/wails/v2/pkg/clilogger"
+ "github.com/wailsapp/wails/v2/pkg/git"
+)
+
+// AddSubcommand adds the `init` command for the Wails application
+func AddSubcommand(app *clir.Cli, w io.Writer) error {
+
+ command := app.NewSubCommand("init", "Initialise a new Wails project")
+
+ // Setup template name flag
+ templateName := "vanilla"
+ description := "Name of built-in template to use, path to template or template url."
+ command.StringFlag("t", description, &templateName)
+
+ // Setup project name
+ projectName := ""
+ command.StringFlag("n", "Name of project", &projectName)
+
+ // Setup project directory
+ projectDirectory := ""
+ command.StringFlag("d", "Project directory", &projectDirectory)
+
+ // Quiet Init
+ quiet := false
+ command.BoolFlag("q", "Suppress output to console", &quiet)
+
+ initGit := false
+ gitInstalled := git.IsInstalled()
+ if gitInstalled {
+ // Git Init
+ command.BoolFlag("g", "Initialise git repository", &initGit)
+ }
+
+ // VSCode project files
+ ide := ""
+ command.StringFlag("ide", "Generate IDE project files", &ide)
+
+ // List templates
+ list := false
+ command.BoolFlag("l", "List templates", &list)
+
+ command.Action(func() error {
+
+ // Create logger
+ logger := clilogger.New(w)
+ logger.Mute(quiet)
+
+ // Are we listing templates?
+ if list {
+ app.PrintBanner()
+ err := templates.OutputList(logger)
+ logger.Println("")
+ return err
+ }
+
+ // Validate name
+ if len(projectName) == 0 {
+ logger.Println("ERROR: Project name required")
+ logger.Println("")
+ command.PrintHelp()
+ return nil
+ }
+
+ // Validate IDE option
+ supportedIDEs := slicer.String([]string{"vscode", "goland"})
+ ide = strings.ToLower(ide)
+ if ide != "" {
+ if !supportedIDEs.Contains(ide) {
+ return fmt.Errorf("ide '%s' not supported. Valid values: %s", ide, supportedIDEs.Join(" "))
+ }
+ }
+
+ if !quiet {
+ app.PrintBanner()
+ }
+
+ task := fmt.Sprintf("Initialising Project %s", strings.Title(projectName))
+ logger.Println(task)
+ logger.Println(strings.Repeat("-", len(task)))
+
+ projectFilename, err := filenamify.Filenamify(projectName, filenamify.Options{
+ Replacement: "_",
+ MaxLength: 255,
+ })
+ if err != nil {
+ return err
+ }
+ goBinary, err := exec.LookPath("go")
+ if err != nil {
+ return fmt.Errorf("unable to find Go compiler. Please download and install Go: https://golang.org/dl/")
+ }
+
+ // Get base path and convert to forward slashes
+ goPath := filepath.ToSlash(filepath.Dir(goBinary))
+ // Trim bin directory
+ goSDKPath := strings.TrimSuffix(goPath, "/bin")
+
+ // Create Template Options
+ options := &templates.Options{
+ ProjectName: projectName,
+ TargetDir: projectDirectory,
+ TemplateName: templateName,
+ Logger: logger,
+ IDE: ide,
+ InitGit: initGit,
+ ProjectNameFilename: projectFilename,
+ WailsVersion: app.Version(),
+ GoSDKPath: goSDKPath,
+ }
+
+ // Try to discover author details from git config
+ findAuthorDetails(options)
+
+ return initProject(options, quiet)
+ })
+
+ return nil
+}
+
+// initProject is our main init command
+func initProject(options *templates.Options, quiet bool) error {
+
+ // Start Time
+ start := time.Now()
+
+ // Install the template
+ remote, template, err := templates.Install(options)
+ if err != nil {
+ return err
+ }
+
+ // Install the default assets
+ err = buildassets.Install(options.TargetDir, options.ProjectName)
+ if err != nil {
+ return err
+ }
+
+ // Run `go mod tidy` to ensure `go.sum` is up to date
+ cmd := exec.Command("go", "mod", "tidy")
+ cmd.Dir = options.TargetDir
+ cmd.Stderr = os.Stderr
+ if !quiet {
+ println("")
+ cmd.Stdout = os.Stdout
+ }
+ err = cmd.Run()
+ if err != nil {
+ return err
+ }
+
+ if options.InitGit {
+ err = initGit(options)
+ if err != nil {
+ return err
+ }
+ }
+
+ if quiet {
+ return nil
+ }
+
+ // Output stats
+ elapsed := time.Since(start)
+ options.Logger.Println("")
+ options.Logger.Println("Project Name: " + options.ProjectName)
+ options.Logger.Println("Project Directory: " + options.TargetDir)
+ options.Logger.Println("Project Template: " + options.TemplateName)
+ options.Logger.Println("Template Support: " + template.HelpURL)
+
+ // IDE message
+ switch options.IDE {
+ case "vscode":
+ options.Logger.Println("VSCode config files generated.")
+ case "goland":
+ options.Logger.Println("Goland config files generated.")
+ }
+
+ if options.InitGit {
+ options.Logger.Println("Git repository initialised.")
+ }
+
+ if remote {
+ options.Logger.Println("\nNOTE: You have created a project using a remote template. The Wails project takes no responsibility for 3rd party templates. Only use remote templates that you trust.")
+ }
+
+ options.Logger.Println("")
+ options.Logger.Println(fmt.Sprintf("Initialised project '%s' in %s.", options.ProjectName, elapsed.Round(time.Millisecond).String()))
+ options.Logger.Println("")
+
+ return nil
+}
+
+func initGit(options *templates.Options) error {
+ err := git.InitRepo(options.TargetDir)
+ if err != nil {
+ return errors.Wrap(err, "Unable to initialise git repository:")
+ }
+
+ return nil
+}
+
+// findAuthorDetails tries to find the user's name and email
+// from gitconfig. If it finds them, it stores them in the project options
+func findAuthorDetails(options *templates.Options) {
+ if git.IsInstalled() {
+ name, err := git.Name()
+ if err == nil {
+ options.AuthorName = strings.TrimSpace(name)
+ }
+
+ email, err := git.Email()
+ if err == nil {
+ options.AuthorEmail = strings.TrimSpace(email)
+ }
+ }
+}
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/ides/goland/gitignore.txt b/v2/cmd/wails/internal/commands/initialise/templates/ides/goland/gitignore.txt
new file mode 100644
index 000000000..73f69e095
--- /dev/null
+++ b/v2/cmd/wails/internal/commands/initialise/templates/ides/goland/gitignore.txt
@@ -0,0 +1,8 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
+# Editor-based HTTP Client requests
+/httpRequests/
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/ides/goland/modules.tmpl.xml b/v2/cmd/wails/internal/commands/initialise/templates/ides/goland/modules.tmpl.xml
new file mode 100644
index 000000000..228a50071
--- /dev/null
+++ b/v2/cmd/wails/internal/commands/initialise/templates/ides/goland/modules.tmpl.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/ides/goland/name.tmpl b/v2/cmd/wails/internal/commands/initialise/templates/ides/goland/name.tmpl
new file mode 100644
index 000000000..8c328a5d3
--- /dev/null
+++ b/v2/cmd/wails/internal/commands/initialise/templates/ides/goland/name.tmpl
@@ -0,0 +1 @@
+{{.ProjectName}}
\ No newline at end of file
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/ides/goland/projectname.iml b/v2/cmd/wails/internal/commands/initialise/templates/ides/goland/projectname.iml
new file mode 100644
index 000000000..5e764c4f0
--- /dev/null
+++ b/v2/cmd/wails/internal/commands/initialise/templates/ides/goland/projectname.iml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/ides/goland/vcs.xml b/v2/cmd/wails/internal/commands/initialise/templates/ides/goland/vcs.xml
new file mode 100644
index 000000000..78f5bc6f7
--- /dev/null
+++ b/v2/cmd/wails/internal/commands/initialise/templates/ides/goland/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/ides/goland/workspace.tmpl.xml b/v2/cmd/wails/internal/commands/initialise/templates/ides/goland/workspace.tmpl.xml
new file mode 100644
index 000000000..42f98045b
--- /dev/null
+++ b/v2/cmd/wails/internal/commands/initialise/templates/ides/goland/workspace.tmpl.xml
@@ -0,0 +1,95 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ >
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+
+
+
+
+
+
\ No newline at end of file
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/ides/vscode/launch.tmpl.json b/v2/cmd/wails/internal/commands/initialise/templates/ides/vscode/launch.tmpl.json
new file mode 100644
index 000000000..d03d5ccdb
--- /dev/null
+++ b/v2/cmd/wails/internal/commands/initialise/templates/ides/vscode/launch.tmpl.json
@@ -0,0 +1,19 @@
+{
+ "version": "0.2.0",
+ "configurations": [
+ {
+ "name": "Wails: Debug {{.ProjectName}}",
+ "type": "go",
+ "request": "launch",
+ "mode": "exec",
+ "program": "${workspaceFolder}/{{.PathToDesktopBinary}}",
+ "preLaunchTask": "build",
+ "cwd": "${workspaceFolder}",
+ "env": {},
+ "args": [
+ "-assetdir",
+ "{{.AssetDir}}"
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/ides/vscode/tasks.tmpl.json b/v2/cmd/wails/internal/commands/initialise/templates/ides/vscode/tasks.tmpl.json
new file mode 100644
index 000000000..03c37e115
--- /dev/null
+++ b/v2/cmd/wails/internal/commands/initialise/templates/ides/vscode/tasks.tmpl.json
@@ -0,0 +1,23 @@
+{
+ "version": "2.0.0",
+ "tasks": [
+ {
+ "label": "build",
+ "type": "shell",
+ "options": {
+ "cwd": "${workspaceFolder}"
+ },
+ "command": "go",
+ "args": [
+ "build",
+ "-tags",
+ "dev",
+ "-gcflags",
+ "all=-N -l",
+ "-o",
+ "{{.PathToDesktopBinary}}"
+ ]
+ }
+ ]
+}
+
\ No newline at end of file
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates.go b/v2/cmd/wails/internal/commands/initialise/templates/templates.go
new file mode 100644
index 000000000..e01fecfb4
--- /dev/null
+++ b/v2/cmd/wails/internal/commands/initialise/templates/templates.go
@@ -0,0 +1,442 @@
+package templates
+
+import (
+ "embed"
+ "encoding/json"
+ "fmt"
+ "github.com/go-git/go-git/v5"
+ gofs "io/fs"
+ "io/ioutil"
+ "log"
+ "os"
+ "path/filepath"
+ "runtime"
+ "strings"
+
+ "github.com/pkg/errors"
+
+ "github.com/leaanthony/debme"
+ "github.com/leaanthony/gosod"
+ "github.com/olekukonko/tablewriter"
+ "github.com/wailsapp/wails/v2/internal/fs"
+ "github.com/wailsapp/wails/v2/pkg/clilogger"
+)
+
+//go:embed templates
+var templates embed.FS
+
+//go:embed ides/*
+var ides embed.FS
+
+// Cahce for the templates
+// We use this because we need different views of the same data
+var templateCache []Template = nil
+
+// Data contains the data we wish to embed during template installation
+type Data struct {
+ ProjectName string
+ BinaryName string
+ WailsVersion string
+ NPMProjectName string
+ AuthorName string
+ AuthorEmail string
+ AuthorNameAndEmail string
+ WailsDirectory string
+ GoSDKPath string
+ AssetDir string
+ WindowsFlags string
+ CGOEnabled string
+ OutputFile string
+}
+
+// Options for installing a template
+type Options struct {
+ ProjectName string
+ TemplateName string
+ BinaryName string
+ TargetDir string
+ Logger *clilogger.CLILogger
+ PathToDesktopBinary string
+ PathToServerBinary string
+ InitGit bool
+ AuthorName string
+ AuthorEmail string
+ AssetDir string
+ IDE string
+ ProjectNameFilename string // The project name but as a valid filename
+ WailsVersion string
+ GoSDKPath string
+ WindowsFlags string
+ CGOEnabled string
+ OutputFile string
+}
+
+// Template holds data relating to a template
+// including the metadata stored in template.json
+type Template struct {
+
+ // Template details
+ Name string `json:"name"`
+ ShortName string `json:"shortname"`
+ Author string `json:"author"`
+ Description string `json:"description"`
+ HelpURL string `json:"helpurl"`
+
+ // Other data
+ FS gofs.FS `json:"-"`
+}
+
+func parseTemplate(template gofs.FS) (Template, error) {
+ var result Template
+ data, err := gofs.ReadFile(template, "template.json")
+ if err != nil {
+ return result, errors.Wrap(err, "Error parsing template")
+ }
+ err = json.Unmarshal(data, &result)
+ if err != nil {
+ return result, err
+ }
+ result.FS = template
+ return result, nil
+}
+
+// List returns the list of available templates
+func List() ([]Template, error) {
+
+ // If the cache isn't loaded, load it
+ if templateCache == nil {
+ err := loadTemplateCache()
+ if err != nil {
+ return nil, err
+ }
+ }
+
+ return templateCache, nil
+}
+
+// getTemplateByShortname returns the template with the given short name
+func getTemplateByShortname(shortname string) (Template, error) {
+
+ var result Template
+
+ // If the cache isn't loaded, load it
+ if templateCache == nil {
+ err := loadTemplateCache()
+ if err != nil {
+ return result, err
+ }
+ }
+
+ for _, template := range templateCache {
+ if template.ShortName == shortname {
+ return template, nil
+ }
+ }
+
+ return result, fmt.Errorf("shortname '%s' is not a valid template shortname", shortname)
+}
+
+// Loads the template cache
+func loadTemplateCache() error {
+
+ templatesFS, err := debme.FS(templates, "templates")
+ if err != nil {
+ return err
+ }
+
+ // Get directories
+ files, err := templatesFS.ReadDir(".")
+ if err != nil {
+ return err
+ }
+
+ // Reset cache
+ templateCache = []Template{}
+
+ for _, file := range files {
+ if file.IsDir() {
+ templateFS, err := templatesFS.FS(file.Name())
+ if err != nil {
+ return err
+ }
+ template, err := parseTemplate(templateFS)
+ if err != nil {
+ // Cannot parse this template, continue
+ continue
+ }
+ templateCache = append(templateCache, template)
+ }
+ }
+
+ return nil
+}
+
+// Install the given template. Returns true if the template is remote.
+func Install(options *Options) (bool, *Template, error) {
+ // Get cwd
+ cwd, err := os.Getwd()
+ if err != nil {
+ return false, nil, err
+ }
+
+ // Did the user want to install in current directory?
+ if options.TargetDir == "" {
+ options.TargetDir = filepath.Join(cwd, options.ProjectName)
+ if fs.DirExists(options.TargetDir) {
+ return false, nil, fmt.Errorf("cannot create project directory. Dir exists: %s", options.TargetDir)
+ }
+ } else {
+ // Get the absolute path of the given directory
+ targetDir, err := filepath.Abs(filepath.Join(cwd, options.TargetDir))
+ if err != nil {
+ return false, nil, err
+ }
+ options.TargetDir = targetDir
+ if !fs.DirExists(options.TargetDir) {
+ err := fs.Mkdir(options.TargetDir)
+ if err != nil {
+ return false, nil, err
+ }
+ }
+ }
+
+ // Flag to indicate remote template
+ remoteTemplate := false
+
+ // Is this a shortname?
+ template, err := getTemplateByShortname(options.TemplateName)
+ if err != nil {
+ // Is this a filepath?
+ templatePath, err := filepath.Abs(options.TemplateName)
+ if fs.DirExists(templatePath) {
+ templateFS := os.DirFS(templatePath)
+ template, err = parseTemplate(templateFS)
+ if err != nil {
+ return false, nil, errors.Wrap(err, "Error installing template")
+ }
+ } else {
+ // git clone to temporary dir
+ tempdir, err := gitclone(options)
+ defer func(path string) {
+ err := os.RemoveAll(path)
+ if err != nil {
+ log.Fatal(err)
+ }
+ }(tempdir)
+ if err != nil {
+ return false, nil, err
+ }
+ // Remove the .git directory
+ err = os.RemoveAll(filepath.Join(tempdir, ".git"))
+ if err != nil {
+ return false, nil, err
+ }
+
+ templateFS := os.DirFS(tempdir)
+ template, err = parseTemplate(templateFS)
+ if err != nil {
+ return false, nil, err
+ }
+ remoteTemplate = true
+ }
+ }
+
+ // Use Gosod to install the template
+ installer := gosod.New(template.FS)
+
+ // Ignore template.json files
+ installer.IgnoreFile("template.json")
+
+ // Setup the data.
+ // We use the directory name for the binary name, like Go
+ BinaryName := filepath.Base(options.TargetDir)
+ NPMProjectName := strings.ToLower(strings.ReplaceAll(BinaryName, " ", ""))
+ localWailsDirectory := fs.RelativePath("../../../../../..")
+
+ templateData := &Data{
+ ProjectName: options.ProjectName,
+ BinaryName: filepath.Base(options.TargetDir),
+ NPMProjectName: NPMProjectName,
+ WailsDirectory: localWailsDirectory,
+ AuthorEmail: options.AuthorEmail,
+ AuthorName: options.AuthorName,
+ WailsVersion: options.WailsVersion,
+ GoSDKPath: options.GoSDKPath,
+ AssetDir: options.AssetDir,
+ }
+
+ // Create a formatted name and email combo.
+ if options.AuthorName != "" {
+ templateData.AuthorNameAndEmail = options.AuthorName + " "
+ }
+ if options.AuthorEmail != "" {
+ templateData.AuthorNameAndEmail += "<" + options.AuthorEmail + ">"
+ }
+ templateData.AuthorNameAndEmail = strings.TrimSpace(templateData.AuthorNameAndEmail)
+
+ installer.RenameFiles(map[string]string{
+ "gitignore.txt": ".gitignore",
+ })
+
+ // Extract the template
+ err = installer.Extract(options.TargetDir, templateData)
+ if err != nil {
+ return false, nil, err
+ }
+
+ err = generateIDEFiles(options)
+ if err != nil {
+ return false, nil, err
+ }
+
+ return remoteTemplate, &template, nil
+}
+
+// Clones the given uri and returns the temporary cloned directory
+func gitclone(options *Options) (string, error) {
+ // Create temporary directory
+ dirname, err := ioutil.TempDir("", "wails-template-*")
+ if err != nil {
+ return "", err
+ }
+ _, err = git.PlainClone(dirname, false, &git.CloneOptions{
+ URL: options.TemplateName,
+ })
+
+ return dirname, err
+
+}
+
+// OutputList prints the list of available tempaltes to the given logger
+func OutputList(logger *clilogger.CLILogger) error {
+ templates, err := List()
+ if err != nil {
+ return err
+ }
+
+ table := tablewriter.NewWriter(logger.Writer)
+ table.SetHeader([]string{"Template", "Short Name", "Description"})
+ table.SetAutoWrapText(false)
+ table.SetAutoFormatHeaders(true)
+ table.SetHeaderAlignment(tablewriter.ALIGN_LEFT)
+ table.SetAlignment(tablewriter.ALIGN_LEFT)
+ table.SetCenterSeparator("")
+ table.SetColumnSeparator("")
+ table.SetRowSeparator("")
+ table.SetHeaderLine(false)
+ table.SetBorder(false)
+ table.SetTablePadding("\t") // pad with tabs
+ table.SetNoWhiteSpace(true)
+ for _, template := range templates {
+ table.Append([]string{template.Name, template.ShortName, template.Description})
+ }
+ table.Render()
+ return nil
+}
+
+func generateIDEFiles(options *Options) error {
+
+ switch options.IDE {
+ case "vscode":
+ return generateVSCodeFiles(options)
+ case "goland":
+ return generateGolandFiles(options)
+ }
+
+ return nil
+}
+
+type ideOptions struct {
+ name string
+ targetDir string
+ options *Options
+ renameFiles map[string]string
+ ignoredFiles []string
+}
+
+func generateGolandFiles(options *Options) error {
+ ideoptions := ideOptions{
+ name: "goland",
+ targetDir: filepath.Join(options.TargetDir, ".idea"),
+ options: options,
+ renameFiles: map[string]string{
+ "projectname.iml": options.ProjectNameFilename + ".iml",
+ "gitignore.txt": ".gitignore",
+ "name": ".name",
+ },
+ }
+ if !options.InitGit {
+ ideoptions.ignoredFiles = []string{"vcs.xml"}
+ }
+ err := installIDEFiles(ideoptions)
+ if err != nil {
+ return errors.Wrap(err, "generating Goland IDE files")
+ }
+
+ return nil
+}
+
+func generateVSCodeFiles(options *Options) error {
+ ideoptions := ideOptions{
+ name: "vscode",
+ targetDir: filepath.Join(options.TargetDir, ".vscode"),
+ options: options,
+ }
+ return installIDEFiles(ideoptions)
+
+}
+
+func installIDEFiles(o ideOptions) error {
+ source, err := debme.FS(ides, "ides/"+o.name)
+ if err != nil {
+ return err
+ }
+
+ // Use gosod to install the template
+ installer := gosod.New(source)
+
+ if o.renameFiles != nil {
+ installer.RenameFiles(o.renameFiles)
+ }
+
+ for _, ignoreFile := range o.ignoredFiles {
+ installer.IgnoreFile(ignoreFile)
+ }
+
+ binaryName := filepath.Base(o.options.TargetDir)
+ if runtime.GOOS == "windows" {
+ // yay windows
+ binaryName += ".exe"
+ }
+
+ // Parse wails.json for assetdir
+ wailsJSONBytes, err := os.ReadFile(filepath.Join(o.options.TargetDir, "wails.json"))
+ if err != nil {
+ return err
+ }
+ var wailsJSON map[string]interface{}
+ err = json.Unmarshal(wailsJSONBytes, &wailsJSON)
+ if err != nil {
+ return err
+ }
+ assetDir := wailsJSON["assetdir"]
+ if assetDir == "" {
+ return fmt.Errorf("Unable to find 'assetdir' in 'wails.json' ")
+ }
+
+ o.options.AssetDir = assetDir.(string)
+ o.options.PathToDesktopBinary = filepath.ToSlash(filepath.Join("build", "bin", binaryName))
+
+ o.options.WindowsFlags = ""
+ o.options.CGOEnabled = "1"
+ if runtime.GOOS == "windows" {
+ o.options.WindowsFlags = " -H windowsgui"
+ o.options.CGOEnabled = "0"
+ }
+ err = installer.Extract(o.targetDir, o.options)
+ if err != nil {
+ return err
+ }
+
+ return nil
+}
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates/svelte/README.md b/v2/cmd/wails/internal/commands/initialise/templates/templates/svelte/README.md
new file mode 100644
index 000000000..45c57ab69
--- /dev/null
+++ b/v2/cmd/wails/internal/commands/initialise/templates/templates/svelte/README.md
@@ -0,0 +1,22 @@
+# README
+
+## About
+
+This is a basic Svelte template, using rollup to bundle the assets into a single JS file.
+Rollup is configured to do the following:
+
+- Convert imported images to base64 strings
+- Convert `url()` in `@font-face` declarations to base64 strings
+- Bundle all css into the JS bundle
+- Copy `index.html` from `frontend/src/` to `frontend/dist/`
+
+Clicking the button will call the backend.
+
+## Live Development
+
+To run in live development mode, run `wails dev` in the project directory. The frontend dev server will run
+on http://localhost:34115. Open this in your browser to connect to your application.
+
+## Building
+
+For a production build, use `wails build`.
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates/svelte/app.go b/v2/cmd/wails/internal/commands/initialise/templates/templates/svelte/app.go
new file mode 100644
index 000000000..d03f9fc11
--- /dev/null
+++ b/v2/cmd/wails/internal/commands/initialise/templates/templates/svelte/app.go
@@ -0,0 +1,37 @@
+package main
+
+import (
+ "context"
+ "fmt"
+)
+
+// App application struct
+type App struct {
+ ctx context.Context
+}
+
+// NewApp creates a new App application struct
+func NewApp() *App {
+ return &App{}
+}
+
+// startup is called at application startup
+func (b *App) startup(ctx context.Context) {
+ // Perform your setup here
+ b.ctx = ctx
+}
+
+// domReady is called after the front-end dom has been loaded
+func (b *App) domReady(ctx context.Context) {
+ // Add your action here
+}
+
+// shutdown is called at application termination
+func (b *App) shutdown(ctx context.Context) {
+ // Perform your teardown here
+}
+
+// Greet returns a greeting for the given name
+func (b *App) Greet(name string) string {
+ return fmt.Sprintf("Hello %s!", name)
+}
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates/svelte/frontend/.gitignore b/v2/cmd/wails/internal/commands/initialise/templates/templates/svelte/frontend/.gitignore
new file mode 100644
index 000000000..ba0af2a15
--- /dev/null
+++ b/v2/cmd/wails/internal/commands/initialise/templates/templates/svelte/frontend/.gitignore
@@ -0,0 +1,4 @@
+/node_modules/
+/dist/build/
+
+.DS_Store
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates/svelte/frontend/README.md b/v2/cmd/wails/internal/commands/initialise/templates/templates/svelte/frontend/README.md
new file mode 100644
index 000000000..7b1ba8363
--- /dev/null
+++ b/v2/cmd/wails/internal/commands/initialise/templates/templates/svelte/frontend/README.md
@@ -0,0 +1,105 @@
+*Looking for a shareable component template? Go here --> [sveltejs/component-template](https://github.com/sveltejs/component-template)*
+
+---
+
+# svelte app
+
+This is a project template for [Svelte](https://svelte.dev) apps. It lives at https://github.com/sveltejs/template.
+
+To create a new project based on this template using [degit](https://github.com/Rich-Harris/degit):
+
+```bash
+npx degit sveltejs/template svelte-app
+cd svelte-app
+```
+
+*Note that you will need to have [Node.js](https://nodejs.org) installed.*
+
+
+## Get started
+
+Install the dependencies...
+
+```bash
+cd svelte-app
+npm install
+```
+
+...then start [Rollup](https://rollupjs.org):
+
+```bash
+npm run dev
+```
+
+Navigate to [localhost:5000](http://localhost:5000). You should see your app running. Edit a component file in `src`, save it, and reload the page to see your changes.
+
+By default, the server will only respond to requests from localhost. To allow connections from other computers, edit the `sirv` commands in package.json to include the option `--host 0.0.0.0`.
+
+If you're using [Visual Studio Code](https://code.visualstudio.com/) we recommend installing the official extension [Svelte for VS Code](https://marketplace.visualstudio.com/items?itemName=svelte.svelte-vscode). If you are using other editors you may need to install a plugin in order to get syntax highlighting and intellisense.
+
+## Building and running in production mode
+
+To create an optimised version of the app:
+
+```bash
+npm run build
+```
+
+You can run the newly built app with `npm run start`. This uses [sirv](https://github.com/lukeed/sirv), which is included in your package.json's `dependencies` so that the app will work when you deploy to platforms like [Heroku](https://heroku.com).
+
+
+## Single-page app mode
+
+By default, sirv will only respond to requests that match files in `public`. This is to maximise compatibility with static fileservers, allowing you to deploy your app anywhere.
+
+If you're building a single-page app (SPA) with multiple routes, sirv needs to be able to respond to requests for *any* path. You can make it so by editing the `"start"` command in package.json:
+
+```js
+"start": "sirv public --single"
+```
+
+## Using TypeScript
+
+This template comes with a script to set up a TypeScript development environment, you can run it immediately after cloning the template with:
+
+```bash
+node scripts/setupTypeScript.js
+```
+
+Or remove the script via:
+
+```bash
+rm scripts/setupTypeScript.js
+```
+
+## Deploying to the web
+
+### With [Vercel](https://vercel.com)
+
+Install `vercel` if you haven't already:
+
+```bash
+npm install -g vercel
+```
+
+Then, from within your project folder:
+
+```bash
+cd public
+vercel deploy --name my-project
+```
+
+### With [surge](https://surge.sh/)
+
+Install `surge` if you haven't already:
+
+```bash
+npm install -g surge
+```
+
+Then, from within your project folder:
+
+```bash
+npm run build
+surge public my-project.surge.sh
+```
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates/svelte/frontend/dist/index.html b/v2/cmd/wails/internal/commands/initialise/templates/templates/svelte/frontend/dist/index.html
new file mode 100644
index 000000000..58f98f0d1
--- /dev/null
+++ b/v2/cmd/wails/internal/commands/initialise/templates/templates/svelte/frontend/dist/index.html
@@ -0,0 +1 @@
+
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates/svelte/frontend/package-lock.tmpl.json b/v2/cmd/wails/internal/commands/initialise/templates/templates/svelte/frontend/package-lock.tmpl.json
new file mode 100644
index 000000000..f5c7c84cc
--- /dev/null
+++ b/v2/cmd/wails/internal/commands/initialise/templates/templates/svelte/frontend/package-lock.tmpl.json
@@ -0,0 +1,3638 @@
+{
+ "name": "{{.ProjectName}}",
+ "version": "1.0.0",
+ "lockfileVersion": 1,
+ "requires": true,
+ "dependencies": {
+ "@babel/code-frame": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.14.5.tgz",
+ "integrity": "sha512-9pzDqyc6OLDaqe+zbACgFkb6fKMNG6CObKpnYXChRsvYGyEdc7CA2BaqeOM+vOtCS5ndmJicPJhKAwYRI6UfFw==",
+ "dev": true,
+ "requires": {
+ "@babel/highlight": "^7.14.5"
+ }
+ },
+ "@babel/helper-validator-identifier": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.5.tgz",
+ "integrity": "sha512-5lsetuxCLilmVGyiLEfoHBRX8UCFD+1m2x3Rj97WrW3V7H3u4RWRXA4evMjImCsin2J2YT0QaVDGf+z8ondbAg==",
+ "dev": true
+ },
+ "@babel/highlight": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.5.tgz",
+ "integrity": "sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-validator-identifier": "^7.14.5",
+ "chalk": "^2.0.0",
+ "js-tokens": "^4.0.0"
+ }
+ },
+ "@nodelib/fs.scandir": {
+ "version": "2.1.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
+ "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
+ "dev": true,
+ "requires": {
+ "@nodelib/fs.stat": "2.0.5",
+ "run-parallel": "^1.1.9"
+ }
+ },
+ "@nodelib/fs.stat": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
+ "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
+ "dev": true
+ },
+ "@nodelib/fs.walk": {
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.7.tgz",
+ "integrity": "sha512-BTIhocbPBSrRmHxOAJFtR18oLhxTtAFDAvL8hY1S3iU8k+E60W/YFs4jrixGzQjMpF4qPXxIQHcjVD9dz1C2QA==",
+ "dev": true,
+ "requires": {
+ "@nodelib/fs.scandir": "2.1.5",
+ "fastq": "^1.6.0"
+ }
+ },
+ "@polka/url": {
+ "version": "1.0.0-next.15",
+ "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.15.tgz",
+ "integrity": "sha512-15spi3V28QdevleWBNXE4pIls3nFZmBbUGrW9IVPwiQczuSb9n76TCB4bsk8TSel+I1OkHEdPhu5QKMfY6rQHA=="
+ },
+ "@rollup/plugin-commonjs": {
+ "version": "17.1.0",
+ "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-17.1.0.tgz",
+ "integrity": "sha512-PoMdXCw0ZyvjpCMT5aV4nkL0QywxP29sODQsSGeDpr/oI49Qq9tRtAsb/LbYbDzFlOydVEqHmmZWFtXJEAX9ew==",
+ "dev": true,
+ "requires": {
+ "@rollup/pluginutils": "^3.1.0",
+ "commondir": "^1.0.1",
+ "estree-walker": "^2.0.1",
+ "glob": "^7.1.6",
+ "is-reference": "^1.2.1",
+ "magic-string": "^0.25.7",
+ "resolve": "^1.17.0"
+ }
+ },
+ "@rollup/plugin-image": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/@rollup/plugin-image/-/plugin-image-2.0.6.tgz",
+ "integrity": "sha512-bB+spXogbPiFjhBS7i8ajUOgOnVwWK3bnJ6VroxKey/q8/EPRkoSh+4O1qPCw97qMIDspF4TlzXVBhZ7nojIPw==",
+ "dev": true,
+ "requires": {
+ "@rollup/pluginutils": "^3.1.0",
+ "mini-svg-data-uri": "^1.2.3"
+ }
+ },
+ "@rollup/plugin-node-resolve": {
+ "version": "11.2.1",
+ "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-11.2.1.tgz",
+ "integrity": "sha512-yc2n43jcqVyGE2sqV5/YCmocy9ArjVAP/BeXyTtADTBBX6V0e5UMqwO8CdQ0kzjb6zu5P1qMzsScCMRvE9OlVg==",
+ "dev": true,
+ "requires": {
+ "@rollup/pluginutils": "^3.1.0",
+ "@types/resolve": "1.17.1",
+ "builtin-modules": "^3.1.0",
+ "deepmerge": "^4.2.2",
+ "is-module": "^1.0.0",
+ "resolve": "^1.19.0"
+ }
+ },
+ "@rollup/pluginutils": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-3.1.0.tgz",
+ "integrity": "sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==",
+ "dev": true,
+ "requires": {
+ "@types/estree": "0.0.39",
+ "estree-walker": "^1.0.1",
+ "picomatch": "^2.2.2"
+ },
+ "dependencies": {
+ "estree-walker": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz",
+ "integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==",
+ "dev": true
+ }
+ }
+ },
+ "@types/estree": {
+ "version": "0.0.39",
+ "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz",
+ "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==",
+ "dev": true
+ },
+ "@types/fs-extra": {
+ "version": "8.1.1",
+ "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-8.1.1.tgz",
+ "integrity": "sha512-TcUlBem321DFQzBNuz8p0CLLKp0VvF/XH9E4KHNmgwyp4E3AfgI5cjiIVZWlbfThBop2qxFIh4+LeY6hVWWZ2w==",
+ "dev": true,
+ "requires": {
+ "@types/node": "*"
+ }
+ },
+ "@types/glob": {
+ "version": "7.1.3",
+ "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.3.tgz",
+ "integrity": "sha512-SEYeGAIQIQX8NN6LDKprLjbrd5dARM5EXsd8GI/A5l0apYI1fGMWgPHSe4ZKL4eozlAyI+doUE9XbYS4xCkQ1w==",
+ "dev": true,
+ "requires": {
+ "@types/minimatch": "*",
+ "@types/node": "*"
+ }
+ },
+ "@types/minimatch": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.4.tgz",
+ "integrity": "sha512-1z8k4wzFnNjVK/tlxvrWuK5WMt6mydWWP7+zvH5eFep4oj+UkrfiJTRtjCeBXNpwaA/FYqqtb4/QS4ianFpIRA==",
+ "dev": true
+ },
+ "@types/node": {
+ "version": "15.12.5",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-15.12.5.tgz",
+ "integrity": "sha512-se3yX7UHv5Bscf8f1ERKvQOD6sTyycH3hdaoozvaLxgUiY5lIGEeH37AD0G0Qi9kPqihPn0HOfd2yaIEN9VwEg==",
+ "dev": true
+ },
+ "@types/q": {
+ "version": "1.5.4",
+ "resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.4.tgz",
+ "integrity": "sha512-1HcDas8SEj4z1Wc696tH56G8OlRaH/sqZOynNNB+HF0WOeXPaxTtbYzJY2oEfiUxjSKjhCKr+MvR7dCHcEelug==",
+ "dev": true
+ },
+ "@types/resolve": {
+ "version": "1.17.1",
+ "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz",
+ "integrity": "sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==",
+ "dev": true,
+ "requires": {
+ "@types/node": "*"
+ }
+ },
+ "alphanum-sort": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/alphanum-sort/-/alphanum-sort-1.0.2.tgz",
+ "integrity": "sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM=",
+ "dev": true
+ },
+ "ansi-styles": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
+ "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+ "dev": true,
+ "requires": {
+ "color-convert": "^1.9.0"
+ }
+ },
+ "anymatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz",
+ "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==",
+ "dev": true,
+ "requires": {
+ "normalize-path": "^3.0.0",
+ "picomatch": "^2.0.4"
+ }
+ },
+ "argparse": {
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
+ "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
+ "dev": true,
+ "requires": {
+ "sprintf-js": "~1.0.2"
+ }
+ },
+ "array-union": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
+ "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==",
+ "dev": true
+ },
+ "balanced-match": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+ "dev": true
+ },
+ "big.js": {
+ "version": "5.2.2",
+ "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz",
+ "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==",
+ "dev": true
+ },
+ "binary-extensions": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
+ "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
+ "dev": true
+ },
+ "boolbase": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
+ "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=",
+ "dev": true
+ },
+ "brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "dev": true,
+ "requires": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "braces": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
+ "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
+ "dev": true,
+ "requires": {
+ "fill-range": "^7.0.1"
+ }
+ },
+ "browserslist": {
+ "version": "4.16.6",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.6.tgz",
+ "integrity": "sha512-Wspk/PqO+4W9qp5iUTJsa1B/QrYn1keNCcEP5OvP7WBwT4KaDly0uONYmC6Xa3Z5IqnUgS0KcgLYu1l74x0ZXQ==",
+ "dev": true,
+ "requires": {
+ "caniuse-lite": "^1.0.30001219",
+ "colorette": "^1.2.2",
+ "electron-to-chromium": "^1.3.723",
+ "escalade": "^3.1.1",
+ "node-releases": "^1.1.71"
+ }
+ },
+ "buffer-from": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz",
+ "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==",
+ "dev": true
+ },
+ "builtin-modules": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.2.0.tgz",
+ "integrity": "sha512-lGzLKcioL90C7wMczpkY0n/oART3MbBa8R9OFGE1rJxoVI86u4WAGfEk8Wjv10eKSyTHVGkSo3bvBylCEtk7LA==",
+ "dev": true
+ },
+ "call-bind": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz",
+ "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==",
+ "dev": true,
+ "requires": {
+ "function-bind": "^1.1.1",
+ "get-intrinsic": "^1.0.2"
+ }
+ },
+ "caller-callsite": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/caller-callsite/-/caller-callsite-2.0.0.tgz",
+ "integrity": "sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ=",
+ "dev": true,
+ "requires": {
+ "callsites": "^2.0.0"
+ }
+ },
+ "caller-path": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-2.0.0.tgz",
+ "integrity": "sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ=",
+ "dev": true,
+ "requires": {
+ "caller-callsite": "^2.0.0"
+ }
+ },
+ "callsites": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz",
+ "integrity": "sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA=",
+ "dev": true
+ },
+ "caniuse-api": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz",
+ "integrity": "sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==",
+ "dev": true,
+ "requires": {
+ "browserslist": "^4.0.0",
+ "caniuse-lite": "^1.0.0",
+ "lodash.memoize": "^4.1.2",
+ "lodash.uniq": "^4.5.0"
+ }
+ },
+ "caniuse-lite": {
+ "version": "1.0.30001241",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001241.tgz",
+ "integrity": "sha512-1uoSZ1Pq1VpH0WerIMqwptXHNNGfdl7d1cJUFs80CwQ/lVzdhTvsFZCeNFslze7AjsQnb4C85tzclPa1VShbeQ==",
+ "dev": true
+ },
+ "chalk": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+ "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
+ }
+ },
+ "chokidar": {
+ "version": "3.5.2",
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.2.tgz",
+ "integrity": "sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ==",
+ "dev": true,
+ "requires": {
+ "anymatch": "~3.1.2",
+ "braces": "~3.0.2",
+ "fsevents": "~2.3.2",
+ "glob-parent": "~5.1.2",
+ "is-binary-path": "~2.1.0",
+ "is-glob": "~4.0.1",
+ "normalize-path": "~3.0.0",
+ "readdirp": "~3.6.0"
+ }
+ },
+ "coa": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/coa/-/coa-2.0.2.tgz",
+ "integrity": "sha512-q5/jG+YQnSy4nRTV4F7lPepBJZ8qBNJJDBuJdoejDyLXgmL7IEo+Le2JDZudFTFt7mrCqIRaSjws4ygRCTCAXA==",
+ "dev": true,
+ "requires": {
+ "@types/q": "^1.5.1",
+ "chalk": "^2.4.1",
+ "q": "^1.1.2"
+ }
+ },
+ "color": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/color/-/color-3.1.3.tgz",
+ "integrity": "sha512-xgXAcTHa2HeFCGLE9Xs/R82hujGtu9Jd9x4NW3T34+OMs7VoPsjwzRczKHvTAHeJwWFwX5j15+MgAppE8ztObQ==",
+ "dev": true,
+ "requires": {
+ "color-convert": "^1.9.1",
+ "color-string": "^1.5.4"
+ }
+ },
+ "color-convert": {
+ "version": "1.9.3",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
+ "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+ "dev": true,
+ "requires": {
+ "color-name": "1.1.3"
+ }
+ },
+ "color-name": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+ "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
+ "dev": true
+ },
+ "color-string": {
+ "version": "1.5.5",
+ "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.5.5.tgz",
+ "integrity": "sha512-jgIoum0OfQfq9Whcfc2z/VhCNcmQjWbey6qBX0vqt7YICflUmBCh9E9CiQD5GSJ+Uehixm3NUwHVhqUAWRivZg==",
+ "dev": true,
+ "requires": {
+ "color-name": "^1.0.0",
+ "simple-swizzle": "^0.2.2"
+ }
+ },
+ "colorette": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.2.tgz",
+ "integrity": "sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w==",
+ "dev": true
+ },
+ "commander": {
+ "version": "2.20.3",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
+ "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
+ "dev": true
+ },
+ "commondir": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz",
+ "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=",
+ "dev": true
+ },
+ "concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
+ "dev": true
+ },
+ "concat-with-sourcemaps": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/concat-with-sourcemaps/-/concat-with-sourcemaps-1.1.0.tgz",
+ "integrity": "sha512-4gEjHJFT9e+2W/77h/DS5SGUgwDaOwprX8L/gl5+3ixnzkVJJsZWDSelmN3Oilw3LNDZjZV0yqH1hLG3k6nghg==",
+ "dev": true,
+ "requires": {
+ "source-map": "^0.6.1"
+ },
+ "dependencies": {
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ }
+ }
+ },
+ "console-clear": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/console-clear/-/console-clear-1.1.1.tgz",
+ "integrity": "sha512-pMD+MVR538ipqkG5JXeOEbKWS5um1H4LUUccUQG68qpeqBYbzYy79Gh55jkd2TtPdRfUaLWdv6LPP//5Zt0aPQ=="
+ },
+ "cosmiconfig": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.1.tgz",
+ "integrity": "sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==",
+ "dev": true,
+ "requires": {
+ "import-fresh": "^2.0.0",
+ "is-directory": "^0.3.1",
+ "js-yaml": "^3.13.1",
+ "parse-json": "^4.0.0"
+ }
+ },
+ "css-color-names": {
+ "version": "0.0.4",
+ "resolved": "https://registry.npmjs.org/css-color-names/-/css-color-names-0.0.4.tgz",
+ "integrity": "sha1-gIrcLnnPhHOAabZGyyDsJ762KeA=",
+ "dev": true
+ },
+ "css-declaration-sorter": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-4.0.1.tgz",
+ "integrity": "sha512-BcxQSKTSEEQUftYpBVnsH4SF05NTuBokb19/sBt6asXGKZ/6VP7PLG1CBCkFDYOnhXhPh0jMhO6xZ71oYHXHBA==",
+ "dev": true,
+ "requires": {
+ "postcss": "^7.0.1",
+ "timsort": "^0.3.0"
+ },
+ "dependencies": {
+ "postcss": {
+ "version": "7.0.36",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.36.tgz",
+ "integrity": "sha512-BebJSIUMwJHRH0HAQoxN4u1CN86glsrwsW0q7T+/m44eXOUAxSNdHRkNZPYz5vVUbg17hFgOQDE7fZk7li3pZw==",
+ "dev": true,
+ "requires": {
+ "chalk": "^2.4.2",
+ "source-map": "^0.6.1",
+ "supports-color": "^6.1.0"
+ }
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz",
+ "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
+ }
+ }
+ },
+ "css-select": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/css-select/-/css-select-2.1.0.tgz",
+ "integrity": "sha512-Dqk7LQKpwLoH3VovzZnkzegqNSuAziQyNZUcrdDM401iY+R5NkGBXGmtO05/yaXQziALuPogeG0b7UAgjnTJTQ==",
+ "dev": true,
+ "requires": {
+ "boolbase": "^1.0.0",
+ "css-what": "^3.2.1",
+ "domutils": "^1.7.0",
+ "nth-check": "^1.0.2"
+ }
+ },
+ "css-select-base-adapter": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/css-select-base-adapter/-/css-select-base-adapter-0.1.1.tgz",
+ "integrity": "sha512-jQVeeRG70QI08vSTwf1jHxp74JoZsr2XSgETae8/xC8ovSnL2WF87GTLO86Sbwdt2lK4Umg4HnnwMO4YF3Ce7w==",
+ "dev": true
+ },
+ "css-tree": {
+ "version": "1.0.0-alpha.37",
+ "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.37.tgz",
+ "integrity": "sha512-DMxWJg0rnz7UgxKT0Q1HU/L9BeJI0M6ksor0OgqOnF+aRCDWg/N2641HmVyU9KVIu0OVVWOb2IpC9A+BJRnejg==",
+ "dev": true,
+ "requires": {
+ "mdn-data": "2.0.4",
+ "source-map": "^0.6.1"
+ },
+ "dependencies": {
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ }
+ }
+ },
+ "css-what": {
+ "version": "3.4.2",
+ "resolved": "https://registry.npmjs.org/css-what/-/css-what-3.4.2.tgz",
+ "integrity": "sha512-ACUm3L0/jiZTqfzRM3Hi9Q8eZqd6IK37mMWPLz9PJxkLWllYeRf+EHUSHYEtFop2Eqytaq1FizFVh7XfBnXCDQ==",
+ "dev": true
+ },
+ "cssesc": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
+ "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==",
+ "dev": true
+ },
+ "cssnano": {
+ "version": "4.1.11",
+ "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-4.1.11.tgz",
+ "integrity": "sha512-6gZm2htn7xIPJOHY824ERgj8cNPgPxyCSnkXc4v7YvNW+TdVfzgngHcEhy/8D11kUWRUMbke+tC+AUcUsnMz2g==",
+ "dev": true,
+ "requires": {
+ "cosmiconfig": "^5.0.0",
+ "cssnano-preset-default": "^4.0.8",
+ "is-resolvable": "^1.0.0",
+ "postcss": "^7.0.0"
+ },
+ "dependencies": {
+ "postcss": {
+ "version": "7.0.36",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.36.tgz",
+ "integrity": "sha512-BebJSIUMwJHRH0HAQoxN4u1CN86glsrwsW0q7T+/m44eXOUAxSNdHRkNZPYz5vVUbg17hFgOQDE7fZk7li3pZw==",
+ "dev": true,
+ "requires": {
+ "chalk": "^2.4.2",
+ "source-map": "^0.6.1",
+ "supports-color": "^6.1.0"
+ }
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz",
+ "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
+ }
+ }
+ },
+ "cssnano-preset-default": {
+ "version": "4.0.8",
+ "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-4.0.8.tgz",
+ "integrity": "sha512-LdAyHuq+VRyeVREFmuxUZR1TXjQm8QQU/ktoo/x7bz+SdOge1YKc5eMN6pRW7YWBmyq59CqYba1dJ5cUukEjLQ==",
+ "dev": true,
+ "requires": {
+ "css-declaration-sorter": "^4.0.1",
+ "cssnano-util-raw-cache": "^4.0.1",
+ "postcss": "^7.0.0",
+ "postcss-calc": "^7.0.1",
+ "postcss-colormin": "^4.0.3",
+ "postcss-convert-values": "^4.0.1",
+ "postcss-discard-comments": "^4.0.2",
+ "postcss-discard-duplicates": "^4.0.2",
+ "postcss-discard-empty": "^4.0.1",
+ "postcss-discard-overridden": "^4.0.1",
+ "postcss-merge-longhand": "^4.0.11",
+ "postcss-merge-rules": "^4.0.3",
+ "postcss-minify-font-values": "^4.0.2",
+ "postcss-minify-gradients": "^4.0.2",
+ "postcss-minify-params": "^4.0.2",
+ "postcss-minify-selectors": "^4.0.2",
+ "postcss-normalize-charset": "^4.0.1",
+ "postcss-normalize-display-values": "^4.0.2",
+ "postcss-normalize-positions": "^4.0.2",
+ "postcss-normalize-repeat-style": "^4.0.2",
+ "postcss-normalize-string": "^4.0.2",
+ "postcss-normalize-timing-functions": "^4.0.2",
+ "postcss-normalize-unicode": "^4.0.1",
+ "postcss-normalize-url": "^4.0.1",
+ "postcss-normalize-whitespace": "^4.0.2",
+ "postcss-ordered-values": "^4.1.2",
+ "postcss-reduce-initial": "^4.0.3",
+ "postcss-reduce-transforms": "^4.0.2",
+ "postcss-svgo": "^4.0.3",
+ "postcss-unique-selectors": "^4.0.1"
+ },
+ "dependencies": {
+ "postcss": {
+ "version": "7.0.36",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.36.tgz",
+ "integrity": "sha512-BebJSIUMwJHRH0HAQoxN4u1CN86glsrwsW0q7T+/m44eXOUAxSNdHRkNZPYz5vVUbg17hFgOQDE7fZk7li3pZw==",
+ "dev": true,
+ "requires": {
+ "chalk": "^2.4.2",
+ "source-map": "^0.6.1",
+ "supports-color": "^6.1.0"
+ }
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz",
+ "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
+ }
+ }
+ },
+ "cssnano-util-get-arguments": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/cssnano-util-get-arguments/-/cssnano-util-get-arguments-4.0.0.tgz",
+ "integrity": "sha1-7ToIKZ8h11dBsg87gfGU7UnMFQ8=",
+ "dev": true
+ },
+ "cssnano-util-get-match": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/cssnano-util-get-match/-/cssnano-util-get-match-4.0.0.tgz",
+ "integrity": "sha1-wOTKB/U4a7F+xeUiULT1lhNlFW0=",
+ "dev": true
+ },
+ "cssnano-util-raw-cache": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/cssnano-util-raw-cache/-/cssnano-util-raw-cache-4.0.1.tgz",
+ "integrity": "sha512-qLuYtWK2b2Dy55I8ZX3ky1Z16WYsx544Q0UWViebptpwn/xDBmog2TLg4f+DBMg1rJ6JDWtn96WHbOKDWt1WQA==",
+ "dev": true,
+ "requires": {
+ "postcss": "^7.0.0"
+ },
+ "dependencies": {
+ "postcss": {
+ "version": "7.0.36",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.36.tgz",
+ "integrity": "sha512-BebJSIUMwJHRH0HAQoxN4u1CN86glsrwsW0q7T+/m44eXOUAxSNdHRkNZPYz5vVUbg17hFgOQDE7fZk7li3pZw==",
+ "dev": true,
+ "requires": {
+ "chalk": "^2.4.2",
+ "source-map": "^0.6.1",
+ "supports-color": "^6.1.0"
+ }
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz",
+ "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
+ }
+ }
+ },
+ "cssnano-util-same-parent": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/cssnano-util-same-parent/-/cssnano-util-same-parent-4.0.1.tgz",
+ "integrity": "sha512-WcKx5OY+KoSIAxBW6UBBRay1U6vkYheCdjyVNDm85zt5K9mHoGOfsOsqIszfAqrQQFIIKgjh2+FDgIj/zsl21Q==",
+ "dev": true
+ },
+ "csso": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/csso/-/csso-4.2.0.tgz",
+ "integrity": "sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA==",
+ "dev": true,
+ "requires": {
+ "css-tree": "^1.1.2"
+ },
+ "dependencies": {
+ "css-tree": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz",
+ "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==",
+ "dev": true,
+ "requires": {
+ "mdn-data": "2.0.14",
+ "source-map": "^0.6.1"
+ }
+ },
+ "mdn-data": {
+ "version": "2.0.14",
+ "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz",
+ "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==",
+ "dev": true
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ }
+ }
+ },
+ "cuint": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/cuint/-/cuint-0.2.2.tgz",
+ "integrity": "sha1-QICG1AlVDCYxFVYZ6fp7ytw7mRs=",
+ "dev": true
+ },
+ "deepmerge": {
+ "version": "4.2.2",
+ "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz",
+ "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==",
+ "dev": true
+ },
+ "define-properties": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz",
+ "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==",
+ "dev": true,
+ "requires": {
+ "object-keys": "^1.0.12"
+ }
+ },
+ "dir-glob": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
+ "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==",
+ "dev": true,
+ "requires": {
+ "path-type": "^4.0.0"
+ }
+ },
+ "dom-serializer": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz",
+ "integrity": "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==",
+ "dev": true,
+ "requires": {
+ "domelementtype": "^2.0.1",
+ "entities": "^2.0.0"
+ },
+ "dependencies": {
+ "domelementtype": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz",
+ "integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==",
+ "dev": true
+ }
+ }
+ },
+ "domelementtype": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz",
+ "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==",
+ "dev": true
+ },
+ "domutils": {
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz",
+ "integrity": "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==",
+ "dev": true,
+ "requires": {
+ "dom-serializer": "0",
+ "domelementtype": "1"
+ }
+ },
+ "dot-prop": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz",
+ "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==",
+ "dev": true,
+ "requires": {
+ "is-obj": "^2.0.0"
+ }
+ },
+ "electron-to-chromium": {
+ "version": "1.3.762",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.762.tgz",
+ "integrity": "sha512-LehWjRpfPcK8F1Lf/NZoAwWLWnjJVo0SZeQ9j/tvnBWYcT99qDqgo4raAfS2oTKZjPrR/jxruh85DGgDUmywEA==",
+ "dev": true
+ },
+ "emojis-list": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz",
+ "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==",
+ "dev": true
+ },
+ "entities": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz",
+ "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==",
+ "dev": true
+ },
+ "error-ex": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
+ "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
+ "dev": true,
+ "requires": {
+ "is-arrayish": "^0.2.1"
+ }
+ },
+ "es-abstract": {
+ "version": "1.18.3",
+ "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.3.tgz",
+ "integrity": "sha512-nQIr12dxV7SSxE6r6f1l3DtAeEYdsGpps13dR0TwJg1S8gyp4ZPgy3FZcHBgbiQqnoqSTb+oC+kO4UQ0C/J8vw==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "es-to-primitive": "^1.2.1",
+ "function-bind": "^1.1.1",
+ "get-intrinsic": "^1.1.1",
+ "has": "^1.0.3",
+ "has-symbols": "^1.0.2",
+ "is-callable": "^1.2.3",
+ "is-negative-zero": "^2.0.1",
+ "is-regex": "^1.1.3",
+ "is-string": "^1.0.6",
+ "object-inspect": "^1.10.3",
+ "object-keys": "^1.1.1",
+ "object.assign": "^4.1.2",
+ "string.prototype.trimend": "^1.0.4",
+ "string.prototype.trimstart": "^1.0.4",
+ "unbox-primitive": "^1.0.1"
+ }
+ },
+ "es-to-primitive": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz",
+ "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==",
+ "dev": true,
+ "requires": {
+ "is-callable": "^1.1.4",
+ "is-date-object": "^1.0.1",
+ "is-symbol": "^1.0.2"
+ }
+ },
+ "escalade": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
+ "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==",
+ "dev": true
+ },
+ "escape-string-regexp": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+ "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
+ "dev": true
+ },
+ "esprima": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
+ "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
+ "dev": true
+ },
+ "estree-walker": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
+ "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==",
+ "dev": true
+ },
+ "eventemitter3": {
+ "version": "4.0.7",
+ "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz",
+ "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==",
+ "dev": true
+ },
+ "fast-glob": {
+ "version": "3.2.6",
+ "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.6.tgz",
+ "integrity": "sha512-GnLuqj/pvQ7pX8/L4J84nijv6sAnlwvSDpMkJi9i7nPmPxGtRPkBSStfvDW5l6nMdX9VWe+pkKWFTgD+vF2QSQ==",
+ "dev": true,
+ "requires": {
+ "@nodelib/fs.stat": "^2.0.2",
+ "@nodelib/fs.walk": "^1.2.3",
+ "glob-parent": "^5.1.2",
+ "merge2": "^1.3.0",
+ "micromatch": "^4.0.4"
+ }
+ },
+ "fastq": {
+ "version": "1.11.0",
+ "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.11.0.tgz",
+ "integrity": "sha512-7Eczs8gIPDrVzT+EksYBcupqMyxSHXXrHOLRRxU2/DicV8789MRBRR8+Hc2uWzUupOs4YS4JzBmBxjjCVBxD/g==",
+ "dev": true,
+ "requires": {
+ "reusify": "^1.0.4"
+ }
+ },
+ "fill-range": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
+ "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
+ "dev": true,
+ "requires": {
+ "to-regex-range": "^5.0.1"
+ }
+ },
+ "fs-extra": {
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz",
+ "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "^4.2.0",
+ "jsonfile": "^4.0.0",
+ "universalify": "^0.1.0"
+ }
+ },
+ "fs.realpath": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
+ "dev": true
+ },
+ "fsevents": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
+ "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
+ "dev": true,
+ "optional": true
+ },
+ "function-bind": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
+ "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
+ "dev": true
+ },
+ "generic-names": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/generic-names/-/generic-names-2.0.1.tgz",
+ "integrity": "sha512-kPCHWa1m9wGG/OwQpeweTwM/PYiQLrUIxXbt/P4Nic3LbGjCP0YwrALHW1uNLKZ0LIMg+RF+XRlj2ekT9ZlZAQ==",
+ "dev": true,
+ "requires": {
+ "loader-utils": "^1.1.0"
+ }
+ },
+ "get-intrinsic": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz",
+ "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==",
+ "dev": true,
+ "requires": {
+ "function-bind": "^1.1.1",
+ "has": "^1.0.3",
+ "has-symbols": "^1.0.1"
+ }
+ },
+ "get-port": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/get-port/-/get-port-3.2.0.tgz",
+ "integrity": "sha1-3Xzn3hh8Bsi/NTeWrHHgmfCYDrw="
+ },
+ "glob": {
+ "version": "7.1.7",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz",
+ "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==",
+ "dev": true,
+ "requires": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.0.4",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ }
+ },
+ "glob-parent": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+ "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+ "dev": true,
+ "requires": {
+ "is-glob": "^4.0.1"
+ }
+ },
+ "globby": {
+ "version": "10.0.1",
+ "resolved": "https://registry.npmjs.org/globby/-/globby-10.0.1.tgz",
+ "integrity": "sha512-sSs4inE1FB2YQiymcmTv6NWENryABjUNPeWhOvmn4SjtKybglsyPZxFB3U1/+L1bYi0rNZDqCLlHyLYDl1Pq5A==",
+ "dev": true,
+ "requires": {
+ "@types/glob": "^7.1.1",
+ "array-union": "^2.1.0",
+ "dir-glob": "^3.0.1",
+ "fast-glob": "^3.0.3",
+ "glob": "^7.1.3",
+ "ignore": "^5.1.1",
+ "merge2": "^1.2.3",
+ "slash": "^3.0.0"
+ }
+ },
+ "graceful-fs": {
+ "version": "4.2.6",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz",
+ "integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==",
+ "dev": true
+ },
+ "has": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
+ "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
+ "dev": true,
+ "requires": {
+ "function-bind": "^1.1.1"
+ }
+ },
+ "has-bigints": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz",
+ "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==",
+ "dev": true
+ },
+ "has-flag": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+ "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
+ "dev": true
+ },
+ "has-symbols": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz",
+ "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==",
+ "dev": true
+ },
+ "hex-color-regex": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/hex-color-regex/-/hex-color-regex-1.1.0.tgz",
+ "integrity": "sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ==",
+ "dev": true
+ },
+ "hsl-regex": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/hsl-regex/-/hsl-regex-1.0.0.tgz",
+ "integrity": "sha1-1JMwx4ntgZ4nakwNJy3/owsY/m4=",
+ "dev": true
+ },
+ "hsla-regex": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/hsla-regex/-/hsla-regex-1.0.0.tgz",
+ "integrity": "sha1-wc56MWjIxmFAM6S194d/OyJfnDg=",
+ "dev": true
+ },
+ "icss-replace-symbols": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/icss-replace-symbols/-/icss-replace-symbols-1.1.0.tgz",
+ "integrity": "sha1-Bupvg2ead0njhs/h/oEq5dsiPe0=",
+ "dev": true
+ },
+ "icss-utils": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz",
+ "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==",
+ "dev": true
+ },
+ "ignore": {
+ "version": "5.1.8",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz",
+ "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==",
+ "dev": true
+ },
+ "import-cwd": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/import-cwd/-/import-cwd-3.0.0.tgz",
+ "integrity": "sha512-4pnzH16plW+hgvRECbDWpQl3cqtvSofHWh44met7ESfZ8UZOWWddm8hEyDTqREJ9RbYHY8gi8DqmaelApoOGMg==",
+ "dev": true,
+ "requires": {
+ "import-from": "^3.0.0"
+ }
+ },
+ "import-fresh": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz",
+ "integrity": "sha1-2BNVwVYS04bGH53dOSLUMEgipUY=",
+ "dev": true,
+ "requires": {
+ "caller-path": "^2.0.0",
+ "resolve-from": "^3.0.0"
+ }
+ },
+ "import-from": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/import-from/-/import-from-3.0.0.tgz",
+ "integrity": "sha512-CiuXOFFSzkU5x/CR0+z7T91Iht4CXgfCxVOFRhh2Zyhg5wOpWvvDLQUsWl+gcN+QscYBjez8hDCt85O7RLDttQ==",
+ "dev": true,
+ "requires": {
+ "resolve-from": "^5.0.0"
+ },
+ "dependencies": {
+ "resolve-from": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz",
+ "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==",
+ "dev": true
+ }
+ }
+ },
+ "indexes-of": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/indexes-of/-/indexes-of-1.0.1.tgz",
+ "integrity": "sha1-8w9xbI4r00bHtn0985FVZqfAVgc=",
+ "dev": true
+ },
+ "inflight": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+ "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
+ "dev": true,
+ "requires": {
+ "once": "^1.3.0",
+ "wrappy": "1"
+ }
+ },
+ "inherits": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
+ "dev": true
+ },
+ "is-absolute-url": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-2.1.0.tgz",
+ "integrity": "sha1-UFMN+4T8yap9vnhS6Do3uTufKqY=",
+ "dev": true
+ },
+ "is-arrayish": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
+ "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=",
+ "dev": true
+ },
+ "is-bigint": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.2.tgz",
+ "integrity": "sha512-0JV5+SOCQkIdzjBK9buARcV804Ddu7A0Qet6sHi3FimE9ne6m4BGQZfRn+NZiXbBk4F4XmHfDZIipLj9pX8dSA==",
+ "dev": true
+ },
+ "is-binary-path": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
+ "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
+ "dev": true,
+ "requires": {
+ "binary-extensions": "^2.0.0"
+ }
+ },
+ "is-boolean-object": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.1.tgz",
+ "integrity": "sha512-bXdQWkECBUIAcCkeH1unwJLIpZYaa5VvuygSyS/c2lf719mTKZDU5UdDRlpd01UjADgmW8RfqaP+mRaVPdr/Ng==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2"
+ }
+ },
+ "is-callable": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.3.tgz",
+ "integrity": "sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ==",
+ "dev": true
+ },
+ "is-color-stop": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/is-color-stop/-/is-color-stop-1.1.0.tgz",
+ "integrity": "sha1-z/9HGu5N1cnhWFmPvhKWe1za00U=",
+ "dev": true,
+ "requires": {
+ "css-color-names": "^0.0.4",
+ "hex-color-regex": "^1.1.0",
+ "hsl-regex": "^1.0.0",
+ "hsla-regex": "^1.0.0",
+ "rgb-regex": "^1.0.1",
+ "rgba-regex": "^1.0.0"
+ }
+ },
+ "is-core-module": {
+ "version": "2.4.0",
+ "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.4.0.tgz",
+ "integrity": "sha512-6A2fkfq1rfeQZjxrZJGerpLCTHRNEBiSgnu0+obeJpEPZRUooHgsizvzv0ZjJwOz3iWIHdJtVWJ/tmPr3D21/A==",
+ "dev": true,
+ "requires": {
+ "has": "^1.0.3"
+ }
+ },
+ "is-date-object": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.4.tgz",
+ "integrity": "sha512-/b4ZVsG7Z5XVtIxs/h9W8nvfLgSAyKYdtGWQLbqy6jA1icmgjf8WCoTKgeS4wy5tYaPePouzFMANbnj94c2Z+A==",
+ "dev": true
+ },
+ "is-directory": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz",
+ "integrity": "sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE=",
+ "dev": true
+ },
+ "is-extglob": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+ "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
+ "dev": true
+ },
+ "is-glob": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz",
+ "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==",
+ "dev": true,
+ "requires": {
+ "is-extglob": "^2.1.1"
+ }
+ },
+ "is-module": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz",
+ "integrity": "sha1-Mlj7afeMFNW4FdZkM2tM/7ZEFZE=",
+ "dev": true
+ },
+ "is-negative-zero": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.1.tgz",
+ "integrity": "sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w==",
+ "dev": true
+ },
+ "is-number": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+ "dev": true
+ },
+ "is-number-object": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.5.tgz",
+ "integrity": "sha512-RU0lI/n95pMoUKu9v1BZP5MBcZuNSVJkMkAG2dJqC4z2GlkGUNeH68SuHuBKBD/XFe+LHZ+f9BKkLET60Niedw==",
+ "dev": true
+ },
+ "is-obj": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz",
+ "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==",
+ "dev": true
+ },
+ "is-plain-object": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-3.0.1.tgz",
+ "integrity": "sha512-Xnpx182SBMrr/aBik8y+GuR4U1L9FqMSojwDQwPMmxyC6bvEqly9UBCxhauBF5vNh2gwWJNX6oDV7O+OM4z34g==",
+ "dev": true
+ },
+ "is-reference": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-1.2.1.tgz",
+ "integrity": "sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==",
+ "dev": true,
+ "requires": {
+ "@types/estree": "*"
+ }
+ },
+ "is-regex": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.3.tgz",
+ "integrity": "sha512-qSVXFz28HM7y+IWX6vLCsexdlvzT1PJNFSBuaQLQ5o0IEw8UDYW6/2+eCMVyIsbM8CNLX2a/QWmSpyxYEHY7CQ==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "has-symbols": "^1.0.2"
+ }
+ },
+ "is-resolvable": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz",
+ "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==",
+ "dev": true
+ },
+ "is-string": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.6.tgz",
+ "integrity": "sha512-2gdzbKUuqtQ3lYNrUTQYoClPhm7oQu4UdpSZMp1/DGgkHBT8E2Z1l0yMdb6D4zNAxwDiMv8MdulKROJGNl0Q0w==",
+ "dev": true
+ },
+ "is-symbol": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz",
+ "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==",
+ "dev": true,
+ "requires": {
+ "has-symbols": "^1.0.2"
+ }
+ },
+ "jest-worker": {
+ "version": "26.6.2",
+ "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.6.2.tgz",
+ "integrity": "sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==",
+ "dev": true,
+ "requires": {
+ "@types/node": "*",
+ "merge-stream": "^2.0.0",
+ "supports-color": "^7.0.0"
+ },
+ "dependencies": {
+ "has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^4.0.0"
+ }
+ }
+ }
+ },
+ "js-tokens": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
+ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
+ "dev": true
+ },
+ "js-yaml": {
+ "version": "3.14.1",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz",
+ "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==",
+ "dev": true,
+ "requires": {
+ "argparse": "^1.0.7",
+ "esprima": "^4.0.0"
+ }
+ },
+ "json-parse-better-errors": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz",
+ "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==",
+ "dev": true
+ },
+ "json5": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz",
+ "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==",
+ "dev": true,
+ "requires": {
+ "minimist": "^1.2.0"
+ }
+ },
+ "jsonfile": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
+ "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "^4.1.6"
+ }
+ },
+ "kleur": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz",
+ "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w=="
+ },
+ "lilconfig": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.0.3.tgz",
+ "integrity": "sha512-EHKqr/+ZvdKCifpNrJCKxBTgk5XupZA3y/aCPY9mxfgBzmgh93Mt/WqjjQ38oMxXuvDokaKiM3lAgvSH2sjtHg==",
+ "dev": true
+ },
+ "livereload": {
+ "version": "0.9.3",
+ "resolved": "https://registry.npmjs.org/livereload/-/livereload-0.9.3.tgz",
+ "integrity": "sha512-q7Z71n3i4X0R9xthAryBdNGVGAO2R5X+/xXpmKeuPMrteg+W2U8VusTKV3YiJbXZwKsOlFlHe+go6uSNjfxrZw==",
+ "dev": true,
+ "requires": {
+ "chokidar": "^3.5.0",
+ "livereload-js": "^3.3.1",
+ "opts": ">= 1.2.0",
+ "ws": "^7.4.3"
+ }
+ },
+ "livereload-js": {
+ "version": "3.3.2",
+ "resolved": "https://registry.npmjs.org/livereload-js/-/livereload-js-3.3.2.tgz",
+ "integrity": "sha512-w677WnINxFkuixAoUEXOStewzLYGI76XVag+0JWMMEyjJQKs0ibWZMxkTlB96Lm3EjZ7IeOxVziBEbtxVQqQZA==",
+ "dev": true
+ },
+ "loader-utils": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz",
+ "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==",
+ "dev": true,
+ "requires": {
+ "big.js": "^5.2.2",
+ "emojis-list": "^3.0.0",
+ "json5": "^1.0.1"
+ }
+ },
+ "local-access": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/local-access/-/local-access-1.1.0.tgz",
+ "integrity": "sha512-XfegD5pyTAfb+GY6chk283Ox5z8WexG56OvM06RWLpAc/UHozO8X6xAxEkIitZOtsSMM1Yr3DkHgW5W+onLhCw=="
+ },
+ "lodash.camelcase": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz",
+ "integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=",
+ "dev": true
+ },
+ "lodash.memoize": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz",
+ "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=",
+ "dev": true
+ },
+ "lodash.uniq": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz",
+ "integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=",
+ "dev": true
+ },
+ "magic-string": {
+ "version": "0.25.7",
+ "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.7.tgz",
+ "integrity": "sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA==",
+ "dev": true,
+ "requires": {
+ "sourcemap-codec": "^1.4.4"
+ }
+ },
+ "make-dir": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
+ "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==",
+ "dev": true,
+ "requires": {
+ "semver": "^6.0.0"
+ }
+ },
+ "mdn-data": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.4.tgz",
+ "integrity": "sha512-iV3XNKw06j5Q7mi6h+9vbx23Tv7JkjEVgKHW4pimwyDGWm0OIQntJJ+u1C6mg6mK1EaTv42XQ7w76yuzH7M2cA==",
+ "dev": true
+ },
+ "merge-stream": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
+ "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==",
+ "dev": true
+ },
+ "merge2": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
+ "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
+ "dev": true
+ },
+ "micromatch": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz",
+ "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==",
+ "dev": true,
+ "requires": {
+ "braces": "^3.0.1",
+ "picomatch": "^2.2.3"
+ }
+ },
+ "mime": {
+ "version": "2.5.2",
+ "resolved": "https://registry.npmjs.org/mime/-/mime-2.5.2.tgz",
+ "integrity": "sha512-tqkh47FzKeCPD2PUiPB6pkbMzsCasjxAfC62/Wap5qrUWcb+sFasXUC5I3gYM5iBM8v/Qpn4UK0x+j0iHyFPDg=="
+ },
+ "mini-svg-data-uri": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/mini-svg-data-uri/-/mini-svg-data-uri-1.3.3.tgz",
+ "integrity": "sha512-+fA2oRcR1dJI/7ITmeQJDrYWks0wodlOz0pAEhKYJ2IVc1z0AnwJUsKY2fzFmPAM3Jo9J0rBx8JAA9QQSJ5PuA==",
+ "dev": true
+ },
+ "minimatch": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
+ "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
+ "dev": true,
+ "requires": {
+ "brace-expansion": "^1.1.7"
+ }
+ },
+ "minimist": {
+ "version": "1.2.5",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
+ "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==",
+ "dev": true
+ },
+ "mkdirp": {
+ "version": "0.5.5",
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz",
+ "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==",
+ "dev": true,
+ "requires": {
+ "minimist": "^1.2.5"
+ }
+ },
+ "mri": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/mri/-/mri-1.1.6.tgz",
+ "integrity": "sha512-oi1b3MfbyGa7FJMP9GmLTttni5JoICpYBRlq+x5V16fZbLsnL9N3wFqqIm/nIG43FjUFkFh9Epzp/kzUGUnJxQ=="
+ },
+ "nanoid": {
+ "version": "3.1.23",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.23.tgz",
+ "integrity": "sha512-FiB0kzdP0FFVGDKlRLEQ1BgDzU87dy5NnzjeW9YZNt+/c3+q82EQDUwniSAUxp/F0gFNI1ZhKU1FqYsMuqZVnw==",
+ "dev": true
+ },
+ "node-releases": {
+ "version": "1.1.73",
+ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.73.tgz",
+ "integrity": "sha512-uW7fodD6pyW2FZNZnp/Z3hvWKeEW1Y8R1+1CnErE8cXFXzl5blBOoVB41CvMer6P6Q0S5FXDwcHgFd1Wj0U9zg==",
+ "dev": true
+ },
+ "normalize-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
+ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
+ "dev": true
+ },
+ "normalize-url": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-3.3.0.tgz",
+ "integrity": "sha512-U+JJi7duF1o+u2pynbp2zXDW2/PADgC30f0GsHZtRh+HOcXHnw137TrNlyxxRvWW5fjKd3bcLHPxofWuCjaeZg==",
+ "dev": true
+ },
+ "nth-check": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz",
+ "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==",
+ "dev": true,
+ "requires": {
+ "boolbase": "~1.0.0"
+ }
+ },
+ "object-inspect": {
+ "version": "1.10.3",
+ "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.10.3.tgz",
+ "integrity": "sha512-e5mCJlSH7poANfC8z8S9s9S2IN5/4Zb3aZ33f5s8YqoazCFzNLloLU8r5VCG+G7WoqLvAAZoVMcy3tp/3X0Plw==",
+ "dev": true
+ },
+ "object-keys": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
+ "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
+ "dev": true
+ },
+ "object.assign": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz",
+ "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.0",
+ "define-properties": "^1.1.3",
+ "has-symbols": "^1.0.1",
+ "object-keys": "^1.1.1"
+ }
+ },
+ "object.getownpropertydescriptors": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.2.tgz",
+ "integrity": "sha512-WtxeKSzfBjlzL+F9b7M7hewDzMwy+C8NRssHd1YrNlzHzIDrXcXiNOMrezdAEM4UXixgV+vvnyBeN7Rygl2ttQ==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.3",
+ "es-abstract": "^1.18.0-next.2"
+ }
+ },
+ "object.values": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.4.tgz",
+ "integrity": "sha512-TnGo7j4XSnKQoK3MfvkzqKCi0nVe/D9I9IjwTNYdb/fxYHpjrluHVOgw0AF6jrRFGMPHdfuidR09tIDiIvnaSg==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.3",
+ "es-abstract": "^1.18.2"
+ }
+ },
+ "once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
+ "dev": true,
+ "requires": {
+ "wrappy": "1"
+ }
+ },
+ "opts": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/opts/-/opts-2.0.2.tgz",
+ "integrity": "sha512-k41FwbcLnlgnFh69f4qdUfvDQ+5vaSDnVPFI/y5XuhKRq97EnVVneO9F1ESVCdiVu4fCS2L8usX3mU331hB7pg==",
+ "dev": true
+ },
+ "p-finally": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz",
+ "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=",
+ "dev": true
+ },
+ "p-queue": {
+ "version": "6.6.2",
+ "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-6.6.2.tgz",
+ "integrity": "sha512-RwFpb72c/BhQLEXIZ5K2e+AhgNVmIejGlTgiB9MzZ0e93GRvqZ7uSi0dvRF7/XIXDeNkra2fNHBxTyPDGySpjQ==",
+ "dev": true,
+ "requires": {
+ "eventemitter3": "^4.0.4",
+ "p-timeout": "^3.2.0"
+ }
+ },
+ "p-timeout": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-3.2.0.tgz",
+ "integrity": "sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==",
+ "dev": true,
+ "requires": {
+ "p-finally": "^1.0.0"
+ }
+ },
+ "parse-json": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz",
+ "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=",
+ "dev": true,
+ "requires": {
+ "error-ex": "^1.3.1",
+ "json-parse-better-errors": "^1.0.1"
+ }
+ },
+ "path-is-absolute": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+ "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
+ "dev": true
+ },
+ "path-parse": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
+ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
+ "dev": true
+ },
+ "path-type": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
+ "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
+ "dev": true
+ },
+ "picomatch": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz",
+ "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==",
+ "dev": true
+ },
+ "pify": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-5.0.0.tgz",
+ "integrity": "sha512-eW/gHNMlxdSP6dmG6uJip6FXN0EQBwm2clYYd8Wul42Cwu/DK8HEftzsapcNdYe2MfLiIwZqsDk2RDEsTE79hA==",
+ "dev": true
+ },
+ "postcss": {
+ "version": "8.3.5",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.3.5.tgz",
+ "integrity": "sha512-NxTuJocUhYGsMiMFHDUkmjSKT3EdH4/WbGF6GCi1NDGk+vbcUTun4fpbOqaPtD8IIsztA2ilZm2DhYCuyN58gA==",
+ "dev": true,
+ "requires": {
+ "colorette": "^1.2.2",
+ "nanoid": "^3.1.23",
+ "source-map-js": "^0.6.2"
+ }
+ },
+ "postcss-calc": {
+ "version": "7.0.5",
+ "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-7.0.5.tgz",
+ "integrity": "sha512-1tKHutbGtLtEZF6PT4JSihCHfIVldU72mZ8SdZHIYriIZ9fh9k9aWSppaT8rHsyI3dX+KSR+W+Ix9BMY3AODrg==",
+ "dev": true,
+ "requires": {
+ "postcss": "^7.0.27",
+ "postcss-selector-parser": "^6.0.2",
+ "postcss-value-parser": "^4.0.2"
+ },
+ "dependencies": {
+ "postcss": {
+ "version": "7.0.36",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.36.tgz",
+ "integrity": "sha512-BebJSIUMwJHRH0HAQoxN4u1CN86glsrwsW0q7T+/m44eXOUAxSNdHRkNZPYz5vVUbg17hFgOQDE7fZk7li3pZw==",
+ "dev": true,
+ "requires": {
+ "chalk": "^2.4.2",
+ "source-map": "^0.6.1",
+ "supports-color": "^6.1.0"
+ }
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz",
+ "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
+ }
+ }
+ },
+ "postcss-colormin": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-4.0.3.tgz",
+ "integrity": "sha512-WyQFAdDZpExQh32j0U0feWisZ0dmOtPl44qYmJKkq9xFWY3p+4qnRzCHeNrkeRhwPHz9bQ3mo0/yVkaply0MNw==",
+ "dev": true,
+ "requires": {
+ "browserslist": "^4.0.0",
+ "color": "^3.0.0",
+ "has": "^1.0.0",
+ "postcss": "^7.0.0",
+ "postcss-value-parser": "^3.0.0"
+ },
+ "dependencies": {
+ "postcss": {
+ "version": "7.0.36",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.36.tgz",
+ "integrity": "sha512-BebJSIUMwJHRH0HAQoxN4u1CN86glsrwsW0q7T+/m44eXOUAxSNdHRkNZPYz5vVUbg17hFgOQDE7fZk7li3pZw==",
+ "dev": true,
+ "requires": {
+ "chalk": "^2.4.2",
+ "source-map": "^0.6.1",
+ "supports-color": "^6.1.0"
+ }
+ },
+ "postcss-value-parser": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz",
+ "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==",
+ "dev": true
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz",
+ "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
+ }
+ }
+ },
+ "postcss-convert-values": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-4.0.1.tgz",
+ "integrity": "sha512-Kisdo1y77KUC0Jmn0OXU/COOJbzM8cImvw1ZFsBgBgMgb1iL23Zs/LXRe3r+EZqM3vGYKdQ2YJVQ5VkJI+zEJQ==",
+ "dev": true,
+ "requires": {
+ "postcss": "^7.0.0",
+ "postcss-value-parser": "^3.0.0"
+ },
+ "dependencies": {
+ "postcss": {
+ "version": "7.0.36",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.36.tgz",
+ "integrity": "sha512-BebJSIUMwJHRH0HAQoxN4u1CN86glsrwsW0q7T+/m44eXOUAxSNdHRkNZPYz5vVUbg17hFgOQDE7fZk7li3pZw==",
+ "dev": true,
+ "requires": {
+ "chalk": "^2.4.2",
+ "source-map": "^0.6.1",
+ "supports-color": "^6.1.0"
+ }
+ },
+ "postcss-value-parser": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz",
+ "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==",
+ "dev": true
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz",
+ "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
+ }
+ }
+ },
+ "postcss-discard-comments": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-4.0.2.tgz",
+ "integrity": "sha512-RJutN259iuRf3IW7GZyLM5Sw4GLTOH8FmsXBnv8Ab/Tc2k4SR4qbV4DNbyyY4+Sjo362SyDmW2DQ7lBSChrpkg==",
+ "dev": true,
+ "requires": {
+ "postcss": "^7.0.0"
+ },
+ "dependencies": {
+ "postcss": {
+ "version": "7.0.36",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.36.tgz",
+ "integrity": "sha512-BebJSIUMwJHRH0HAQoxN4u1CN86glsrwsW0q7T+/m44eXOUAxSNdHRkNZPYz5vVUbg17hFgOQDE7fZk7li3pZw==",
+ "dev": true,
+ "requires": {
+ "chalk": "^2.4.2",
+ "source-map": "^0.6.1",
+ "supports-color": "^6.1.0"
+ }
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz",
+ "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
+ }
+ }
+ },
+ "postcss-discard-duplicates": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-4.0.2.tgz",
+ "integrity": "sha512-ZNQfR1gPNAiXZhgENFfEglF93pciw0WxMkJeVmw8eF+JZBbMD7jp6C67GqJAXVZP2BWbOztKfbsdmMp/k8c6oQ==",
+ "dev": true,
+ "requires": {
+ "postcss": "^7.0.0"
+ },
+ "dependencies": {
+ "postcss": {
+ "version": "7.0.36",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.36.tgz",
+ "integrity": "sha512-BebJSIUMwJHRH0HAQoxN4u1CN86glsrwsW0q7T+/m44eXOUAxSNdHRkNZPYz5vVUbg17hFgOQDE7fZk7li3pZw==",
+ "dev": true,
+ "requires": {
+ "chalk": "^2.4.2",
+ "source-map": "^0.6.1",
+ "supports-color": "^6.1.0"
+ }
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz",
+ "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
+ }
+ }
+ },
+ "postcss-discard-empty": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-4.0.1.tgz",
+ "integrity": "sha512-B9miTzbznhDjTfjvipfHoqbWKwd0Mj+/fL5s1QOz06wufguil+Xheo4XpOnc4NqKYBCNqqEzgPv2aPBIJLox0w==",
+ "dev": true,
+ "requires": {
+ "postcss": "^7.0.0"
+ },
+ "dependencies": {
+ "postcss": {
+ "version": "7.0.36",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.36.tgz",
+ "integrity": "sha512-BebJSIUMwJHRH0HAQoxN4u1CN86glsrwsW0q7T+/m44eXOUAxSNdHRkNZPYz5vVUbg17hFgOQDE7fZk7li3pZw==",
+ "dev": true,
+ "requires": {
+ "chalk": "^2.4.2",
+ "source-map": "^0.6.1",
+ "supports-color": "^6.1.0"
+ }
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz",
+ "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
+ }
+ }
+ },
+ "postcss-discard-overridden": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-4.0.1.tgz",
+ "integrity": "sha512-IYY2bEDD7g1XM1IDEsUT4//iEYCxAmP5oDSFMVU/JVvT7gh+l4fmjciLqGgwjdWpQIdb0Che2VX00QObS5+cTg==",
+ "dev": true,
+ "requires": {
+ "postcss": "^7.0.0"
+ },
+ "dependencies": {
+ "postcss": {
+ "version": "7.0.36",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.36.tgz",
+ "integrity": "sha512-BebJSIUMwJHRH0HAQoxN4u1CN86glsrwsW0q7T+/m44eXOUAxSNdHRkNZPYz5vVUbg17hFgOQDE7fZk7li3pZw==",
+ "dev": true,
+ "requires": {
+ "chalk": "^2.4.2",
+ "source-map": "^0.6.1",
+ "supports-color": "^6.1.0"
+ }
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz",
+ "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
+ }
+ }
+ },
+ "postcss-load-config": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-3.1.0.tgz",
+ "integrity": "sha512-ipM8Ds01ZUophjDTQYSVP70slFSYg3T0/zyfII5vzhN6V57YSxMgG5syXuwi5VtS8wSf3iL30v0uBdoIVx4Q0g==",
+ "dev": true,
+ "requires": {
+ "import-cwd": "^3.0.0",
+ "lilconfig": "^2.0.3",
+ "yaml": "^1.10.2"
+ }
+ },
+ "postcss-merge-longhand": {
+ "version": "4.0.11",
+ "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-4.0.11.tgz",
+ "integrity": "sha512-alx/zmoeXvJjp7L4mxEMjh8lxVlDFX1gqWHzaaQewwMZiVhLo42TEClKaeHbRf6J7j82ZOdTJ808RtN0ZOZwvw==",
+ "dev": true,
+ "requires": {
+ "css-color-names": "0.0.4",
+ "postcss": "^7.0.0",
+ "postcss-value-parser": "^3.0.0",
+ "stylehacks": "^4.0.0"
+ },
+ "dependencies": {
+ "postcss": {
+ "version": "7.0.36",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.36.tgz",
+ "integrity": "sha512-BebJSIUMwJHRH0HAQoxN4u1CN86glsrwsW0q7T+/m44eXOUAxSNdHRkNZPYz5vVUbg17hFgOQDE7fZk7li3pZw==",
+ "dev": true,
+ "requires": {
+ "chalk": "^2.4.2",
+ "source-map": "^0.6.1",
+ "supports-color": "^6.1.0"
+ }
+ },
+ "postcss-value-parser": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz",
+ "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==",
+ "dev": true
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz",
+ "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
+ }
+ }
+ },
+ "postcss-merge-rules": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-4.0.3.tgz",
+ "integrity": "sha512-U7e3r1SbvYzO0Jr3UT/zKBVgYYyhAz0aitvGIYOYK5CPmkNih+WDSsS5tvPrJ8YMQYlEMvsZIiqmn7HdFUaeEQ==",
+ "dev": true,
+ "requires": {
+ "browserslist": "^4.0.0",
+ "caniuse-api": "^3.0.0",
+ "cssnano-util-same-parent": "^4.0.0",
+ "postcss": "^7.0.0",
+ "postcss-selector-parser": "^3.0.0",
+ "vendors": "^1.0.0"
+ },
+ "dependencies": {
+ "postcss": {
+ "version": "7.0.36",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.36.tgz",
+ "integrity": "sha512-BebJSIUMwJHRH0HAQoxN4u1CN86glsrwsW0q7T+/m44eXOUAxSNdHRkNZPYz5vVUbg17hFgOQDE7fZk7li3pZw==",
+ "dev": true,
+ "requires": {
+ "chalk": "^2.4.2",
+ "source-map": "^0.6.1",
+ "supports-color": "^6.1.0"
+ }
+ },
+ "postcss-selector-parser": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-3.1.2.tgz",
+ "integrity": "sha512-h7fJ/5uWuRVyOtkO45pnt1Ih40CEleeyCHzipqAZO2e5H20g25Y48uYnFUiShvY4rZWNJ/Bib/KVPmanaCtOhA==",
+ "dev": true,
+ "requires": {
+ "dot-prop": "^5.2.0",
+ "indexes-of": "^1.0.1",
+ "uniq": "^1.0.1"
+ }
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz",
+ "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
+ }
+ }
+ },
+ "postcss-minify-font-values": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-4.0.2.tgz",
+ "integrity": "sha512-j85oO6OnRU9zPf04+PZv1LYIYOprWm6IA6zkXkrJXyRveDEuQggG6tvoy8ir8ZwjLxLuGfNkCZEQG7zan+Hbtg==",
+ "dev": true,
+ "requires": {
+ "postcss": "^7.0.0",
+ "postcss-value-parser": "^3.0.0"
+ },
+ "dependencies": {
+ "postcss": {
+ "version": "7.0.36",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.36.tgz",
+ "integrity": "sha512-BebJSIUMwJHRH0HAQoxN4u1CN86glsrwsW0q7T+/m44eXOUAxSNdHRkNZPYz5vVUbg17hFgOQDE7fZk7li3pZw==",
+ "dev": true,
+ "requires": {
+ "chalk": "^2.4.2",
+ "source-map": "^0.6.1",
+ "supports-color": "^6.1.0"
+ }
+ },
+ "postcss-value-parser": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz",
+ "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==",
+ "dev": true
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz",
+ "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
+ }
+ }
+ },
+ "postcss-minify-gradients": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-4.0.2.tgz",
+ "integrity": "sha512-qKPfwlONdcf/AndP1U8SJ/uzIJtowHlMaSioKzebAXSG4iJthlWC9iSWznQcX4f66gIWX44RSA841HTHj3wK+Q==",
+ "dev": true,
+ "requires": {
+ "cssnano-util-get-arguments": "^4.0.0",
+ "is-color-stop": "^1.0.0",
+ "postcss": "^7.0.0",
+ "postcss-value-parser": "^3.0.0"
+ },
+ "dependencies": {
+ "postcss": {
+ "version": "7.0.36",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.36.tgz",
+ "integrity": "sha512-BebJSIUMwJHRH0HAQoxN4u1CN86glsrwsW0q7T+/m44eXOUAxSNdHRkNZPYz5vVUbg17hFgOQDE7fZk7li3pZw==",
+ "dev": true,
+ "requires": {
+ "chalk": "^2.4.2",
+ "source-map": "^0.6.1",
+ "supports-color": "^6.1.0"
+ }
+ },
+ "postcss-value-parser": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz",
+ "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==",
+ "dev": true
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz",
+ "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
+ }
+ }
+ },
+ "postcss-minify-params": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-4.0.2.tgz",
+ "integrity": "sha512-G7eWyzEx0xL4/wiBBJxJOz48zAKV2WG3iZOqVhPet/9geefm/Px5uo1fzlHu+DOjT+m0Mmiz3jkQzVHe6wxAWg==",
+ "dev": true,
+ "requires": {
+ "alphanum-sort": "^1.0.0",
+ "browserslist": "^4.0.0",
+ "cssnano-util-get-arguments": "^4.0.0",
+ "postcss": "^7.0.0",
+ "postcss-value-parser": "^3.0.0",
+ "uniqs": "^2.0.0"
+ },
+ "dependencies": {
+ "postcss": {
+ "version": "7.0.36",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.36.tgz",
+ "integrity": "sha512-BebJSIUMwJHRH0HAQoxN4u1CN86glsrwsW0q7T+/m44eXOUAxSNdHRkNZPYz5vVUbg17hFgOQDE7fZk7li3pZw==",
+ "dev": true,
+ "requires": {
+ "chalk": "^2.4.2",
+ "source-map": "^0.6.1",
+ "supports-color": "^6.1.0"
+ }
+ },
+ "postcss-value-parser": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz",
+ "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==",
+ "dev": true
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz",
+ "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
+ }
+ }
+ },
+ "postcss-minify-selectors": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-4.0.2.tgz",
+ "integrity": "sha512-D5S1iViljXBj9kflQo4YutWnJmwm8VvIsU1GeXJGiG9j8CIg9zs4voPMdQDUmIxetUOh60VilsNzCiAFTOqu3g==",
+ "dev": true,
+ "requires": {
+ "alphanum-sort": "^1.0.0",
+ "has": "^1.0.0",
+ "postcss": "^7.0.0",
+ "postcss-selector-parser": "^3.0.0"
+ },
+ "dependencies": {
+ "postcss": {
+ "version": "7.0.36",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.36.tgz",
+ "integrity": "sha512-BebJSIUMwJHRH0HAQoxN4u1CN86glsrwsW0q7T+/m44eXOUAxSNdHRkNZPYz5vVUbg17hFgOQDE7fZk7li3pZw==",
+ "dev": true,
+ "requires": {
+ "chalk": "^2.4.2",
+ "source-map": "^0.6.1",
+ "supports-color": "^6.1.0"
+ }
+ },
+ "postcss-selector-parser": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-3.1.2.tgz",
+ "integrity": "sha512-h7fJ/5uWuRVyOtkO45pnt1Ih40CEleeyCHzipqAZO2e5H20g25Y48uYnFUiShvY4rZWNJ/Bib/KVPmanaCtOhA==",
+ "dev": true,
+ "requires": {
+ "dot-prop": "^5.2.0",
+ "indexes-of": "^1.0.1",
+ "uniq": "^1.0.1"
+ }
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz",
+ "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
+ }
+ }
+ },
+ "postcss-modules": {
+ "version": "4.1.3",
+ "resolved": "https://registry.npmjs.org/postcss-modules/-/postcss-modules-4.1.3.tgz",
+ "integrity": "sha512-dBT39hrXe4OAVYJe/2ZuIZ9BzYhOe7t+IhedYeQ2OxKwDpAGlkEN/fR0fGnrbx4BvgbMReRX4hCubYK9cE/pJQ==",
+ "dev": true,
+ "requires": {
+ "generic-names": "^2.0.1",
+ "icss-replace-symbols": "^1.1.0",
+ "lodash.camelcase": "^4.3.0",
+ "postcss-modules-extract-imports": "^3.0.0",
+ "postcss-modules-local-by-default": "^4.0.0",
+ "postcss-modules-scope": "^3.0.0",
+ "postcss-modules-values": "^4.0.0",
+ "string-hash": "^1.1.1"
+ }
+ },
+ "postcss-modules-extract-imports": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz",
+ "integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==",
+ "dev": true
+ },
+ "postcss-modules-local-by-default": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.0.tgz",
+ "integrity": "sha512-sT7ihtmGSF9yhm6ggikHdV0hlziDTX7oFoXtuVWeDd3hHObNkcHRo9V3yg7vCAY7cONyxJC/XXCmmiHHcvX7bQ==",
+ "dev": true,
+ "requires": {
+ "icss-utils": "^5.0.0",
+ "postcss-selector-parser": "^6.0.2",
+ "postcss-value-parser": "^4.1.0"
+ }
+ },
+ "postcss-modules-scope": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz",
+ "integrity": "sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg==",
+ "dev": true,
+ "requires": {
+ "postcss-selector-parser": "^6.0.4"
+ }
+ },
+ "postcss-modules-values": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz",
+ "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==",
+ "dev": true,
+ "requires": {
+ "icss-utils": "^5.0.0"
+ }
+ },
+ "postcss-normalize-charset": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-4.0.1.tgz",
+ "integrity": "sha512-gMXCrrlWh6G27U0hF3vNvR3w8I1s2wOBILvA87iNXaPvSNo5uZAMYsZG7XjCUf1eVxuPfyL4TJ7++SGZLc9A3g==",
+ "dev": true,
+ "requires": {
+ "postcss": "^7.0.0"
+ },
+ "dependencies": {
+ "postcss": {
+ "version": "7.0.36",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.36.tgz",
+ "integrity": "sha512-BebJSIUMwJHRH0HAQoxN4u1CN86glsrwsW0q7T+/m44eXOUAxSNdHRkNZPYz5vVUbg17hFgOQDE7fZk7li3pZw==",
+ "dev": true,
+ "requires": {
+ "chalk": "^2.4.2",
+ "source-map": "^0.6.1",
+ "supports-color": "^6.1.0"
+ }
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz",
+ "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
+ }
+ }
+ },
+ "postcss-normalize-display-values": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/postcss-normalize-display-values/-/postcss-normalize-display-values-4.0.2.tgz",
+ "integrity": "sha512-3F2jcsaMW7+VtRMAqf/3m4cPFhPD3EFRgNs18u+k3lTJJlVe7d0YPO+bnwqo2xg8YiRpDXJI2u8A0wqJxMsQuQ==",
+ "dev": true,
+ "requires": {
+ "cssnano-util-get-match": "^4.0.0",
+ "postcss": "^7.0.0",
+ "postcss-value-parser": "^3.0.0"
+ },
+ "dependencies": {
+ "postcss": {
+ "version": "7.0.36",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.36.tgz",
+ "integrity": "sha512-BebJSIUMwJHRH0HAQoxN4u1CN86glsrwsW0q7T+/m44eXOUAxSNdHRkNZPYz5vVUbg17hFgOQDE7fZk7li3pZw==",
+ "dev": true,
+ "requires": {
+ "chalk": "^2.4.2",
+ "source-map": "^0.6.1",
+ "supports-color": "^6.1.0"
+ }
+ },
+ "postcss-value-parser": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz",
+ "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==",
+ "dev": true
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz",
+ "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
+ }
+ }
+ },
+ "postcss-normalize-positions": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/postcss-normalize-positions/-/postcss-normalize-positions-4.0.2.tgz",
+ "integrity": "sha512-Dlf3/9AxpxE+NF1fJxYDeggi5WwV35MXGFnnoccP/9qDtFrTArZ0D0R+iKcg5WsUd8nUYMIl8yXDCtcrT8JrdA==",
+ "dev": true,
+ "requires": {
+ "cssnano-util-get-arguments": "^4.0.0",
+ "has": "^1.0.0",
+ "postcss": "^7.0.0",
+ "postcss-value-parser": "^3.0.0"
+ },
+ "dependencies": {
+ "postcss": {
+ "version": "7.0.36",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.36.tgz",
+ "integrity": "sha512-BebJSIUMwJHRH0HAQoxN4u1CN86glsrwsW0q7T+/m44eXOUAxSNdHRkNZPYz5vVUbg17hFgOQDE7fZk7li3pZw==",
+ "dev": true,
+ "requires": {
+ "chalk": "^2.4.2",
+ "source-map": "^0.6.1",
+ "supports-color": "^6.1.0"
+ }
+ },
+ "postcss-value-parser": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz",
+ "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==",
+ "dev": true
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz",
+ "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
+ }
+ }
+ },
+ "postcss-normalize-repeat-style": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-4.0.2.tgz",
+ "integrity": "sha512-qvigdYYMpSuoFs3Is/f5nHdRLJN/ITA7huIoCyqqENJe9PvPmLhNLMu7QTjPdtnVf6OcYYO5SHonx4+fbJE1+Q==",
+ "dev": true,
+ "requires": {
+ "cssnano-util-get-arguments": "^4.0.0",
+ "cssnano-util-get-match": "^4.0.0",
+ "postcss": "^7.0.0",
+ "postcss-value-parser": "^3.0.0"
+ },
+ "dependencies": {
+ "postcss": {
+ "version": "7.0.36",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.36.tgz",
+ "integrity": "sha512-BebJSIUMwJHRH0HAQoxN4u1CN86glsrwsW0q7T+/m44eXOUAxSNdHRkNZPYz5vVUbg17hFgOQDE7fZk7li3pZw==",
+ "dev": true,
+ "requires": {
+ "chalk": "^2.4.2",
+ "source-map": "^0.6.1",
+ "supports-color": "^6.1.0"
+ }
+ },
+ "postcss-value-parser": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz",
+ "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==",
+ "dev": true
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz",
+ "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
+ }
+ }
+ },
+ "postcss-normalize-string": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/postcss-normalize-string/-/postcss-normalize-string-4.0.2.tgz",
+ "integrity": "sha512-RrERod97Dnwqq49WNz8qo66ps0swYZDSb6rM57kN2J+aoyEAJfZ6bMx0sx/F9TIEX0xthPGCmeyiam/jXif0eA==",
+ "dev": true,
+ "requires": {
+ "has": "^1.0.0",
+ "postcss": "^7.0.0",
+ "postcss-value-parser": "^3.0.0"
+ },
+ "dependencies": {
+ "postcss": {
+ "version": "7.0.36",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.36.tgz",
+ "integrity": "sha512-BebJSIUMwJHRH0HAQoxN4u1CN86glsrwsW0q7T+/m44eXOUAxSNdHRkNZPYz5vVUbg17hFgOQDE7fZk7li3pZw==",
+ "dev": true,
+ "requires": {
+ "chalk": "^2.4.2",
+ "source-map": "^0.6.1",
+ "supports-color": "^6.1.0"
+ }
+ },
+ "postcss-value-parser": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz",
+ "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==",
+ "dev": true
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz",
+ "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
+ }
+ }
+ },
+ "postcss-normalize-timing-functions": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-4.0.2.tgz",
+ "integrity": "sha512-acwJY95edP762e++00Ehq9L4sZCEcOPyaHwoaFOhIwWCDfik6YvqsYNxckee65JHLKzuNSSmAdxwD2Cud1Z54A==",
+ "dev": true,
+ "requires": {
+ "cssnano-util-get-match": "^4.0.0",
+ "postcss": "^7.0.0",
+ "postcss-value-parser": "^3.0.0"
+ },
+ "dependencies": {
+ "postcss": {
+ "version": "7.0.36",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.36.tgz",
+ "integrity": "sha512-BebJSIUMwJHRH0HAQoxN4u1CN86glsrwsW0q7T+/m44eXOUAxSNdHRkNZPYz5vVUbg17hFgOQDE7fZk7li3pZw==",
+ "dev": true,
+ "requires": {
+ "chalk": "^2.4.2",
+ "source-map": "^0.6.1",
+ "supports-color": "^6.1.0"
+ }
+ },
+ "postcss-value-parser": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz",
+ "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==",
+ "dev": true
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz",
+ "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
+ }
+ }
+ },
+ "postcss-normalize-unicode": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/postcss-normalize-unicode/-/postcss-normalize-unicode-4.0.1.tgz",
+ "integrity": "sha512-od18Uq2wCYn+vZ/qCOeutvHjB5jm57ToxRaMeNuf0nWVHaP9Hua56QyMF6fs/4FSUnVIw0CBPsU0K4LnBPwYwg==",
+ "dev": true,
+ "requires": {
+ "browserslist": "^4.0.0",
+ "postcss": "^7.0.0",
+ "postcss-value-parser": "^3.0.0"
+ },
+ "dependencies": {
+ "postcss": {
+ "version": "7.0.36",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.36.tgz",
+ "integrity": "sha512-BebJSIUMwJHRH0HAQoxN4u1CN86glsrwsW0q7T+/m44eXOUAxSNdHRkNZPYz5vVUbg17hFgOQDE7fZk7li3pZw==",
+ "dev": true,
+ "requires": {
+ "chalk": "^2.4.2",
+ "source-map": "^0.6.1",
+ "supports-color": "^6.1.0"
+ }
+ },
+ "postcss-value-parser": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz",
+ "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==",
+ "dev": true
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz",
+ "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
+ }
+ }
+ },
+ "postcss-normalize-url": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-4.0.1.tgz",
+ "integrity": "sha512-p5oVaF4+IHwu7VpMan/SSpmpYxcJMtkGppYf0VbdH5B6hN8YNmVyJLuY9FmLQTzY3fag5ESUUHDqM+heid0UVA==",
+ "dev": true,
+ "requires": {
+ "is-absolute-url": "^2.0.0",
+ "normalize-url": "^3.0.0",
+ "postcss": "^7.0.0",
+ "postcss-value-parser": "^3.0.0"
+ },
+ "dependencies": {
+ "postcss": {
+ "version": "7.0.36",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.36.tgz",
+ "integrity": "sha512-BebJSIUMwJHRH0HAQoxN4u1CN86glsrwsW0q7T+/m44eXOUAxSNdHRkNZPYz5vVUbg17hFgOQDE7fZk7li3pZw==",
+ "dev": true,
+ "requires": {
+ "chalk": "^2.4.2",
+ "source-map": "^0.6.1",
+ "supports-color": "^6.1.0"
+ }
+ },
+ "postcss-value-parser": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz",
+ "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==",
+ "dev": true
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz",
+ "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
+ }
+ }
+ },
+ "postcss-normalize-whitespace": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/postcss-normalize-whitespace/-/postcss-normalize-whitespace-4.0.2.tgz",
+ "integrity": "sha512-tO8QIgrsI3p95r8fyqKV+ufKlSHh9hMJqACqbv2XknufqEDhDvbguXGBBqxw9nsQoXWf0qOqppziKJKHMD4GtA==",
+ "dev": true,
+ "requires": {
+ "postcss": "^7.0.0",
+ "postcss-value-parser": "^3.0.0"
+ },
+ "dependencies": {
+ "postcss": {
+ "version": "7.0.36",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.36.tgz",
+ "integrity": "sha512-BebJSIUMwJHRH0HAQoxN4u1CN86glsrwsW0q7T+/m44eXOUAxSNdHRkNZPYz5vVUbg17hFgOQDE7fZk7li3pZw==",
+ "dev": true,
+ "requires": {
+ "chalk": "^2.4.2",
+ "source-map": "^0.6.1",
+ "supports-color": "^6.1.0"
+ }
+ },
+ "postcss-value-parser": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz",
+ "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==",
+ "dev": true
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz",
+ "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
+ }
+ }
+ },
+ "postcss-ordered-values": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-4.1.2.tgz",
+ "integrity": "sha512-2fCObh5UanxvSxeXrtLtlwVThBvHn6MQcu4ksNT2tsaV2Fg76R2CV98W7wNSlX+5/pFwEyaDwKLLoEV7uRybAw==",
+ "dev": true,
+ "requires": {
+ "cssnano-util-get-arguments": "^4.0.0",
+ "postcss": "^7.0.0",
+ "postcss-value-parser": "^3.0.0"
+ },
+ "dependencies": {
+ "postcss": {
+ "version": "7.0.36",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.36.tgz",
+ "integrity": "sha512-BebJSIUMwJHRH0HAQoxN4u1CN86glsrwsW0q7T+/m44eXOUAxSNdHRkNZPYz5vVUbg17hFgOQDE7fZk7li3pZw==",
+ "dev": true,
+ "requires": {
+ "chalk": "^2.4.2",
+ "source-map": "^0.6.1",
+ "supports-color": "^6.1.0"
+ }
+ },
+ "postcss-value-parser": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz",
+ "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==",
+ "dev": true
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz",
+ "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
+ }
+ }
+ },
+ "postcss-reduce-initial": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-4.0.3.tgz",
+ "integrity": "sha512-gKWmR5aUulSjbzOfD9AlJiHCGH6AEVLaM0AV+aSioxUDd16qXP1PCh8d1/BGVvpdWn8k/HiK7n6TjeoXN1F7DA==",
+ "dev": true,
+ "requires": {
+ "browserslist": "^4.0.0",
+ "caniuse-api": "^3.0.0",
+ "has": "^1.0.0",
+ "postcss": "^7.0.0"
+ },
+ "dependencies": {
+ "postcss": {
+ "version": "7.0.36",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.36.tgz",
+ "integrity": "sha512-BebJSIUMwJHRH0HAQoxN4u1CN86glsrwsW0q7T+/m44eXOUAxSNdHRkNZPYz5vVUbg17hFgOQDE7fZk7li3pZw==",
+ "dev": true,
+ "requires": {
+ "chalk": "^2.4.2",
+ "source-map": "^0.6.1",
+ "supports-color": "^6.1.0"
+ }
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz",
+ "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
+ }
+ }
+ },
+ "postcss-reduce-transforms": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-4.0.2.tgz",
+ "integrity": "sha512-EEVig1Q2QJ4ELpJXMZR8Vt5DQx8/mo+dGWSR7vWXqcob2gQLyQGsionYcGKATXvQzMPn6DSN1vTN7yFximdIAg==",
+ "dev": true,
+ "requires": {
+ "cssnano-util-get-match": "^4.0.0",
+ "has": "^1.0.0",
+ "postcss": "^7.0.0",
+ "postcss-value-parser": "^3.0.0"
+ },
+ "dependencies": {
+ "postcss": {
+ "version": "7.0.36",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.36.tgz",
+ "integrity": "sha512-BebJSIUMwJHRH0HAQoxN4u1CN86glsrwsW0q7T+/m44eXOUAxSNdHRkNZPYz5vVUbg17hFgOQDE7fZk7li3pZw==",
+ "dev": true,
+ "requires": {
+ "chalk": "^2.4.2",
+ "source-map": "^0.6.1",
+ "supports-color": "^6.1.0"
+ }
+ },
+ "postcss-value-parser": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz",
+ "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==",
+ "dev": true
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz",
+ "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
+ }
+ }
+ },
+ "postcss-selector-parser": {
+ "version": "6.0.6",
+ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.6.tgz",
+ "integrity": "sha512-9LXrvaaX3+mcv5xkg5kFwqSzSH1JIObIx51PrndZwlmznwXRfxMddDvo9gve3gVR8ZTKgoFDdWkbRFmEhT4PMg==",
+ "dev": true,
+ "requires": {
+ "cssesc": "^3.0.0",
+ "util-deprecate": "^1.0.2"
+ }
+ },
+ "postcss-svgo": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-4.0.3.tgz",
+ "integrity": "sha512-NoRbrcMWTtUghzuKSoIm6XV+sJdvZ7GZSc3wdBN0W19FTtp2ko8NqLsgoh/m9CzNhU3KLPvQmjIwtaNFkaFTvw==",
+ "dev": true,
+ "requires": {
+ "postcss": "^7.0.0",
+ "postcss-value-parser": "^3.0.0",
+ "svgo": "^1.0.0"
+ },
+ "dependencies": {
+ "postcss": {
+ "version": "7.0.36",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.36.tgz",
+ "integrity": "sha512-BebJSIUMwJHRH0HAQoxN4u1CN86glsrwsW0q7T+/m44eXOUAxSNdHRkNZPYz5vVUbg17hFgOQDE7fZk7li3pZw==",
+ "dev": true,
+ "requires": {
+ "chalk": "^2.4.2",
+ "source-map": "^0.6.1",
+ "supports-color": "^6.1.0"
+ }
+ },
+ "postcss-value-parser": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz",
+ "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==",
+ "dev": true
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz",
+ "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
+ }
+ }
+ },
+ "postcss-unique-selectors": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-4.0.1.tgz",
+ "integrity": "sha512-+JanVaryLo9QwZjKrmJgkI4Fn8SBgRO6WXQBJi7KiAVPlmxikB5Jzc4EvXMT2H0/m0RjrVVm9rGNhZddm/8Spg==",
+ "dev": true,
+ "requires": {
+ "alphanum-sort": "^1.0.0",
+ "postcss": "^7.0.0",
+ "uniqs": "^2.0.0"
+ },
+ "dependencies": {
+ "postcss": {
+ "version": "7.0.36",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.36.tgz",
+ "integrity": "sha512-BebJSIUMwJHRH0HAQoxN4u1CN86glsrwsW0q7T+/m44eXOUAxSNdHRkNZPYz5vVUbg17hFgOQDE7fZk7li3pZw==",
+ "dev": true,
+ "requires": {
+ "chalk": "^2.4.2",
+ "source-map": "^0.6.1",
+ "supports-color": "^6.1.0"
+ }
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz",
+ "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
+ }
+ }
+ },
+ "postcss-url": {
+ "version": "10.1.3",
+ "resolved": "https://registry.npmjs.org/postcss-url/-/postcss-url-10.1.3.tgz",
+ "integrity": "sha512-FUzyxfI5l2tKmXdYc6VTu3TWZsInayEKPbiyW+P6vmmIrrb4I6CGX0BFoewgYHLK+oIL5FECEK02REYRpBvUCw==",
+ "dev": true,
+ "requires": {
+ "make-dir": "~3.1.0",
+ "mime": "~2.5.2",
+ "minimatch": "~3.0.4",
+ "xxhashjs": "~0.2.2"
+ }
+ },
+ "postcss-value-parser": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz",
+ "integrity": "sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ==",
+ "dev": true
+ },
+ "promise.series": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/promise.series/-/promise.series-0.2.0.tgz",
+ "integrity": "sha1-LMfr6Vn8OmYZwEq029yeRS2GS70=",
+ "dev": true
+ },
+ "q": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz",
+ "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=",
+ "dev": true
+ },
+ "queue-microtask": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
+ "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
+ "dev": true
+ },
+ "randombytes": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
+ "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==",
+ "dev": true,
+ "requires": {
+ "safe-buffer": "^5.1.0"
+ }
+ },
+ "readdirp": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
+ "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
+ "dev": true,
+ "requires": {
+ "picomatch": "^2.2.1"
+ }
+ },
+ "require-relative": {
+ "version": "0.8.7",
+ "resolved": "https://registry.npmjs.org/require-relative/-/require-relative-0.8.7.tgz",
+ "integrity": "sha1-eZlTn8ngR6N5KPoZb44VY9q9Nt4=",
+ "dev": true
+ },
+ "resolve": {
+ "version": "1.20.0",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz",
+ "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==",
+ "dev": true,
+ "requires": {
+ "is-core-module": "^2.2.0",
+ "path-parse": "^1.0.6"
+ }
+ },
+ "resolve-from": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz",
+ "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=",
+ "dev": true
+ },
+ "reusify": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
+ "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
+ "dev": true
+ },
+ "rgb-regex": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/rgb-regex/-/rgb-regex-1.0.1.tgz",
+ "integrity": "sha1-wODWiC3w4jviVKR16O3UGRX+rrE=",
+ "dev": true
+ },
+ "rgba-regex": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/rgba-regex/-/rgba-regex-1.0.0.tgz",
+ "integrity": "sha1-QzdOLiyglosO8VI0YLfXMP8i7rM=",
+ "dev": true
+ },
+ "rollup": {
+ "version": "2.52.4",
+ "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.52.4.tgz",
+ "integrity": "sha512-AXgUxxWXyGfsj8GKleR1k8KsG8G+7ZZDRU9RZb9PnLGSyTqI/1qf/+QSp1hRaR40j4yfBCKXs5khtGKiFwihfg==",
+ "dev": true,
+ "requires": {
+ "fsevents": "~2.3.2"
+ }
+ },
+ "rollup-plugin-copy": {
+ "version": "3.4.0",
+ "resolved": "https://registry.npmjs.org/rollup-plugin-copy/-/rollup-plugin-copy-3.4.0.tgz",
+ "integrity": "sha512-rGUmYYsYsceRJRqLVlE9FivJMxJ7X6jDlP79fmFkL8sJs7VVMSVyA2yfyL+PGyO/vJs4A87hwhgVfz61njI+uQ==",
+ "dev": true,
+ "requires": {
+ "@types/fs-extra": "^8.0.1",
+ "colorette": "^1.1.0",
+ "fs-extra": "^8.1.0",
+ "globby": "10.0.1",
+ "is-plain-object": "^3.0.0"
+ }
+ },
+ "rollup-plugin-css-only": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/rollup-plugin-css-only/-/rollup-plugin-css-only-3.1.0.tgz",
+ "integrity": "sha512-TYMOE5uoD76vpj+RTkQLzC9cQtbnJNktHPB507FzRWBVaofg7KhIqq1kGbcVOadARSozWF883Ho9KpSPKH8gqA==",
+ "dev": true,
+ "requires": {
+ "@rollup/pluginutils": "4"
+ },
+ "dependencies": {
+ "@rollup/pluginutils": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-4.1.0.tgz",
+ "integrity": "sha512-TrBhfJkFxA+ER+ew2U2/fHbebhLT/l/2pRk0hfj9KusXUuRXd2v0R58AfaZK9VXDQ4TogOSEmICVrQAA3zFnHQ==",
+ "dev": true,
+ "requires": {
+ "estree-walker": "^2.0.1",
+ "picomatch": "^2.2.2"
+ }
+ }
+ }
+ },
+ "rollup-plugin-livereload": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/rollup-plugin-livereload/-/rollup-plugin-livereload-2.0.5.tgz",
+ "integrity": "sha512-vqQZ/UQowTW7VoiKEM5ouNW90wE5/GZLfdWuR0ELxyKOJUIaj+uismPZZaICU4DnWPVjnpCDDxEqwU7pcKY/PA==",
+ "dev": true,
+ "requires": {
+ "livereload": "^0.9.1"
+ }
+ },
+ "rollup-plugin-postcss": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/rollup-plugin-postcss/-/rollup-plugin-postcss-4.0.0.tgz",
+ "integrity": "sha512-OQzT+YspV01/6dxfyEw8lBO2px3hyL8Xn+k2QGctL7V/Yx2Z1QaMKdYVslP1mqv7RsKt6DROIlnbpmgJ3yxf6g==",
+ "dev": true,
+ "requires": {
+ "chalk": "^4.1.0",
+ "concat-with-sourcemaps": "^1.1.0",
+ "cssnano": "^4.1.10",
+ "import-cwd": "^3.0.0",
+ "p-queue": "^6.6.2",
+ "pify": "^5.0.0",
+ "postcss-load-config": "^3.0.0",
+ "postcss-modules": "^4.0.0",
+ "promise.series": "^0.2.0",
+ "resolve": "^1.19.0",
+ "rollup-pluginutils": "^2.8.2",
+ "safe-identifier": "^0.4.2",
+ "style-inject": "^0.3.0"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "requires": {
+ "color-convert": "^2.0.1"
+ }
+ },
+ "chalk": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz",
+ "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ }
+ },
+ "color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "requires": {
+ "color-name": "~1.1.4"
+ }
+ },
+ "color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true
+ },
+ "has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^4.0.0"
+ }
+ }
+ }
+ },
+ "rollup-plugin-svelte": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/rollup-plugin-svelte/-/rollup-plugin-svelte-7.1.0.tgz",
+ "integrity": "sha512-vopCUq3G+25sKjwF5VilIbiY6KCuMNHP1PFvx2Vr3REBNMDllKHFZN2B9jwwC+MqNc3UPKkjXnceLPEjTjXGXg==",
+ "dev": true,
+ "requires": {
+ "require-relative": "^0.8.7",
+ "rollup-pluginutils": "^2.8.2"
+ }
+ },
+ "rollup-plugin-terser": {
+ "version": "7.0.2",
+ "resolved": "https://registry.npmjs.org/rollup-plugin-terser/-/rollup-plugin-terser-7.0.2.tgz",
+ "integrity": "sha512-w3iIaU4OxcF52UUXiZNsNeuXIMDvFrr+ZXK6bFZ0Q60qyVfq4uLptoS4bbq3paG3x216eQllFZX7zt6TIImguQ==",
+ "dev": true,
+ "requires": {
+ "@babel/code-frame": "^7.10.4",
+ "jest-worker": "^26.2.1",
+ "serialize-javascript": "^4.0.0",
+ "terser": "^5.0.0"
+ }
+ },
+ "rollup-pluginutils": {
+ "version": "2.8.2",
+ "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz",
+ "integrity": "sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==",
+ "dev": true,
+ "requires": {
+ "estree-walker": "^0.6.1"
+ },
+ "dependencies": {
+ "estree-walker": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz",
+ "integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==",
+ "dev": true
+ }
+ }
+ },
+ "run-parallel": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
+ "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
+ "dev": true,
+ "requires": {
+ "queue-microtask": "^1.2.2"
+ }
+ },
+ "sade": {
+ "version": "1.7.4",
+ "resolved": "https://registry.npmjs.org/sade/-/sade-1.7.4.tgz",
+ "integrity": "sha512-y5yauMD93rX840MwUJr7C1ysLFBgMspsdTo4UVrDg3fXDvtwOyIqykhVAAm6fk/3au77773itJStObgK+LKaiA==",
+ "requires": {
+ "mri": "^1.1.0"
+ }
+ },
+ "safe-buffer": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
+ "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
+ "dev": true
+ },
+ "safe-identifier": {
+ "version": "0.4.2",
+ "resolved": "https://registry.npmjs.org/safe-identifier/-/safe-identifier-0.4.2.tgz",
+ "integrity": "sha512-6pNbSMW6OhAi9j+N8V+U715yBQsaWJ7eyEUaOrawX+isg5ZxhUlV1NipNtgaKHmFGiABwt+ZF04Ii+3Xjkg+8w==",
+ "dev": true
+ },
+ "sax": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz",
+ "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==",
+ "dev": true
+ },
+ "semiver": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/semiver/-/semiver-1.1.0.tgz",
+ "integrity": "sha512-QNI2ChmuioGC1/xjyYwyZYADILWyW6AmS1UH6gDj/SFUUUS4MBAWs/7mxnkRPc/F4iHezDP+O8t0dO8WHiEOdg=="
+ },
+ "semver": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "dev": true
+ },
+ "serialize-javascript": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz",
+ "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==",
+ "dev": true,
+ "requires": {
+ "randombytes": "^2.1.0"
+ }
+ },
+ "simple-swizzle": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz",
+ "integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=",
+ "dev": true,
+ "requires": {
+ "is-arrayish": "^0.3.1"
+ },
+ "dependencies": {
+ "is-arrayish": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz",
+ "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==",
+ "dev": true
+ }
+ }
+ },
+ "sirv": {
+ "version": "1.0.12",
+ "resolved": "https://registry.npmjs.org/sirv/-/sirv-1.0.12.tgz",
+ "integrity": "sha512-+jQoCxndz7L2tqQL4ZyzfDhky0W/4ZJip3XoOuxyQWnAwMxindLl3Xv1qT4x1YX/re0leShvTm8Uk0kQspGhBg==",
+ "requires": {
+ "@polka/url": "^1.0.0-next.15",
+ "mime": "^2.3.1",
+ "totalist": "^1.0.0"
+ }
+ },
+ "sirv-cli": {
+ "version": "1.0.12",
+ "resolved": "https://registry.npmjs.org/sirv-cli/-/sirv-cli-1.0.12.tgz",
+ "integrity": "sha512-Rs5PvF3a48zuLmrl8vcqVv9xF/WWPES19QawVkpdzqx7vD5SMZS07+ece1gK4umbslXN43YeIksYtQM5csgIzQ==",
+ "requires": {
+ "console-clear": "^1.1.0",
+ "get-port": "^3.2.0",
+ "kleur": "^3.0.0",
+ "local-access": "^1.0.1",
+ "sade": "^1.6.0",
+ "semiver": "^1.0.0",
+ "sirv": "^1.0.12",
+ "tinydate": "^1.0.0"
+ }
+ },
+ "slash": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
+ "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
+ "dev": true
+ },
+ "source-map": {
+ "version": "0.7.3",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz",
+ "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==",
+ "dev": true
+ },
+ "source-map-js": {
+ "version": "0.6.2",
+ "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-0.6.2.tgz",
+ "integrity": "sha512-/3GptzWzu0+0MBQFrDKzw/DvvMTUORvgY6k6jd/VS6iCR4RDTKWH6v6WPwQoUO8667uQEf9Oe38DxAYWY5F/Ug==",
+ "dev": true
+ },
+ "source-map-support": {
+ "version": "0.5.19",
+ "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz",
+ "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==",
+ "dev": true,
+ "requires": {
+ "buffer-from": "^1.0.0",
+ "source-map": "^0.6.0"
+ },
+ "dependencies": {
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ }
+ }
+ },
+ "sourcemap-codec": {
+ "version": "1.4.8",
+ "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz",
+ "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==",
+ "dev": true
+ },
+ "sprintf-js": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
+ "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
+ "dev": true
+ },
+ "stable": {
+ "version": "0.1.8",
+ "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz",
+ "integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==",
+ "dev": true
+ },
+ "string-hash": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/string-hash/-/string-hash-1.1.3.tgz",
+ "integrity": "sha1-6Kr8CsGFW0Zmkp7X3RJ1311sgRs=",
+ "dev": true
+ },
+ "string.prototype.trimend": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz",
+ "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.3"
+ }
+ },
+ "string.prototype.trimstart": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz",
+ "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.3"
+ }
+ },
+ "style-inject": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/style-inject/-/style-inject-0.3.0.tgz",
+ "integrity": "sha512-IezA2qp+vcdlhJaVm5SOdPPTUu0FCEqfNSli2vRuSIBbu5Nq5UvygTk/VzeCqfLz2Atj3dVII5QBKGZRZ0edzw==",
+ "dev": true
+ },
+ "stylehacks": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-4.0.3.tgz",
+ "integrity": "sha512-7GlLk9JwlElY4Y6a/rmbH2MhVlTyVmiJd1PfTCqFaIBEGMYNsrO/v3SeGTdhBThLg4Z+NbOk/qFMwCa+J+3p/g==",
+ "dev": true,
+ "requires": {
+ "browserslist": "^4.0.0",
+ "postcss": "^7.0.0",
+ "postcss-selector-parser": "^3.0.0"
+ },
+ "dependencies": {
+ "postcss": {
+ "version": "7.0.36",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.36.tgz",
+ "integrity": "sha512-BebJSIUMwJHRH0HAQoxN4u1CN86glsrwsW0q7T+/m44eXOUAxSNdHRkNZPYz5vVUbg17hFgOQDE7fZk7li3pZw==",
+ "dev": true,
+ "requires": {
+ "chalk": "^2.4.2",
+ "source-map": "^0.6.1",
+ "supports-color": "^6.1.0"
+ }
+ },
+ "postcss-selector-parser": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-3.1.2.tgz",
+ "integrity": "sha512-h7fJ/5uWuRVyOtkO45pnt1Ih40CEleeyCHzipqAZO2e5H20g25Y48uYnFUiShvY4rZWNJ/Bib/KVPmanaCtOhA==",
+ "dev": true,
+ "requires": {
+ "dot-prop": "^5.2.0",
+ "indexes-of": "^1.0.1",
+ "uniq": "^1.0.1"
+ }
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz",
+ "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
+ }
+ }
+ },
+ "supports-color": {
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+ "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
+ },
+ "svelte": {
+ "version": "3.38.3",
+ "resolved": "https://registry.npmjs.org/svelte/-/svelte-3.38.3.tgz",
+ "integrity": "sha512-N7bBZJH0iF24wsalFZF+fVYMUOigaAUQMIcEKHO3jstK/iL8VmP9xE+P0/a76+FkNcWt+TDv2Gx1taUoUscrvw==",
+ "dev": true
+ },
+ "svgo": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/svgo/-/svgo-1.3.2.tgz",
+ "integrity": "sha512-yhy/sQYxR5BkC98CY7o31VGsg014AKLEPxdfhora76l36hD9Rdy5NZA/Ocn6yayNPgSamYdtX2rFJdcv07AYVw==",
+ "dev": true,
+ "requires": {
+ "chalk": "^2.4.1",
+ "coa": "^2.0.2",
+ "css-select": "^2.0.0",
+ "css-select-base-adapter": "^0.1.1",
+ "css-tree": "1.0.0-alpha.37",
+ "csso": "^4.0.2",
+ "js-yaml": "^3.13.1",
+ "mkdirp": "~0.5.1",
+ "object.values": "^1.1.0",
+ "sax": "~1.2.4",
+ "stable": "^0.1.8",
+ "unquote": "~1.1.1",
+ "util.promisify": "~1.0.0"
+ }
+ },
+ "terser": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/terser/-/terser-5.7.1.tgz",
+ "integrity": "sha512-b3e+d5JbHAe/JSjwsC3Zn55wsBIM7AsHLjKxT31kGCldgbpFePaFo+PiddtO6uwRZWRw7sPXmAN8dTW61xmnSg==",
+ "dev": true,
+ "requires": {
+ "commander": "^2.20.0",
+ "source-map": "~0.7.2",
+ "source-map-support": "~0.5.19"
+ }
+ },
+ "timsort": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/timsort/-/timsort-0.3.0.tgz",
+ "integrity": "sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q=",
+ "dev": true
+ },
+ "tinydate": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/tinydate/-/tinydate-1.3.0.tgz",
+ "integrity": "sha512-7cR8rLy2QhYHpsBDBVYnnWXm8uRTr38RoZakFSW7Bs7PzfMPNZthuMLkwqZv7MTu8lhQ91cOFYS5a7iFj2oR3w=="
+ },
+ "to-regex-range": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+ "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+ "dev": true,
+ "requires": {
+ "is-number": "^7.0.0"
+ }
+ },
+ "totalist": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/totalist/-/totalist-1.1.0.tgz",
+ "integrity": "sha512-gduQwd1rOdDMGxFG1gEvhV88Oirdo2p+KjoYFU7k2g+i7n6AFFbDQ5kMPUsW0pNbfQsB/cwXvT1i4Bue0s9g5g=="
+ },
+ "unbox-primitive": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz",
+ "integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==",
+ "dev": true,
+ "requires": {
+ "function-bind": "^1.1.1",
+ "has-bigints": "^1.0.1",
+ "has-symbols": "^1.0.2",
+ "which-boxed-primitive": "^1.0.2"
+ }
+ },
+ "uniq": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz",
+ "integrity": "sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8=",
+ "dev": true
+ },
+ "uniqs": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/uniqs/-/uniqs-2.0.0.tgz",
+ "integrity": "sha1-/+3ks2slKQaW5uFl1KWe25mOawI=",
+ "dev": true
+ },
+ "universalify": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz",
+ "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==",
+ "dev": true
+ },
+ "unquote": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/unquote/-/unquote-1.1.1.tgz",
+ "integrity": "sha1-j97XMk7G6IoP+LkF58CYzcCG1UQ=",
+ "dev": true
+ },
+ "util-deprecate": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+ "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=",
+ "dev": true
+ },
+ "util.promisify": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.1.tgz",
+ "integrity": "sha512-g9JpC/3He3bm38zsLupWryXHoEcS22YHthuPQSJdMy6KNrzIRzWqcsHzD/WUnqe45whVou4VIsPew37DoXWNrA==",
+ "dev": true,
+ "requires": {
+ "define-properties": "^1.1.3",
+ "es-abstract": "^1.17.2",
+ "has-symbols": "^1.0.1",
+ "object.getownpropertydescriptors": "^2.1.0"
+ }
+ },
+ "vendors": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/vendors/-/vendors-1.0.4.tgz",
+ "integrity": "sha512-/juG65kTL4Cy2su4P8HjtkTxk6VmJDiOPBufWniqQ6wknac6jNiXS9vU+hO3wgusiyqWlzTbVHi0dyJqRONg3w==",
+ "dev": true
+ },
+ "which-boxed-primitive": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz",
+ "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==",
+ "dev": true,
+ "requires": {
+ "is-bigint": "^1.0.1",
+ "is-boolean-object": "^1.1.0",
+ "is-number-object": "^1.0.4",
+ "is-string": "^1.0.5",
+ "is-symbol": "^1.0.3"
+ }
+ },
+ "wrappy": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
+ "dev": true
+ },
+ "ws": {
+ "version": "7.5.1",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.1.tgz",
+ "integrity": "sha512-2c6faOUH/nhoQN6abwMloF7Iyl0ZS2E9HGtsiLrWn0zOOMWlhtDmdf/uihDt6jnuCxgtwGBNy6Onsoy2s2O2Ow==",
+ "dev": true
+ },
+ "xxhashjs": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/xxhashjs/-/xxhashjs-0.2.2.tgz",
+ "integrity": "sha512-AkTuIuVTET12tpsVIQo+ZU6f/qDmKuRUcjaqR+OIvm+aCBsZ95i7UVY5WJ9TMsSaZ0DA2WxoZ4acu0sPH+OKAw==",
+ "dev": true,
+ "requires": {
+ "cuint": "^0.2.2"
+ }
+ },
+ "yaml": {
+ "version": "1.10.2",
+ "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz",
+ "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==",
+ "dev": true
+ }
+ }
+}
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates/svelte/frontend/package.tmpl.json b/v2/cmd/wails/internal/commands/initialise/templates/templates/svelte/frontend/package.tmpl.json
new file mode 100644
index 000000000..a49448c62
--- /dev/null
+++ b/v2/cmd/wails/internal/commands/initialise/templates/templates/svelte/frontend/package.tmpl.json
@@ -0,0 +1,28 @@
+{
+ "name": "{{.ProjectName}}",
+ "version": "1.0.0",
+ "private": true,
+ "scripts": {
+ "build": "rollup -c",
+ "dev": "rollup -c -w",
+ "start": "sirv dist --no-clear"
+ },
+ "devDependencies": {
+ "@rollup/plugin-commonjs": "^17.0.0",
+ "@rollup/plugin-image": "^2.0.6",
+ "@rollup/plugin-node-resolve": "^11.0.0",
+ "postcss": "^8.3.5",
+ "postcss-url": "^10.1.3",
+ "rollup": "^2.3.4",
+ "rollup-plugin-copy": "^3.4.0",
+ "rollup-plugin-livereload": "^2.0.0",
+ "rollup-plugin-postcss": "^4.0.0",
+ "rollup-plugin-svelte": "^7.0.0",
+ "rollup-plugin-terser": "^7.0.0",
+ "svelte": "^3.0.0"
+ },
+ "dependencies": {
+ "sirv-cli": "^1.0.0"
+ },
+ "author": "{{.AuthorName}}"
+}
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates/svelte/frontend/rollup.config.js b/v2/cmd/wails/internal/commands/initialise/templates/templates/svelte/frontend/rollup.config.js
new file mode 100644
index 000000000..42685908c
--- /dev/null
+++ b/v2/cmd/wails/internal/commands/initialise/templates/templates/svelte/frontend/rollup.config.js
@@ -0,0 +1,83 @@
+import svelte from 'rollup-plugin-svelte';
+import commonjs from '@rollup/plugin-commonjs';
+import resolve from '@rollup/plugin-node-resolve';
+import livereload from 'rollup-plugin-livereload';
+import {terser} from 'rollup-plugin-terser';
+import copy from 'rollup-plugin-copy';
+import postcss from 'rollup-plugin-postcss'
+
+const production = !process.env.ROLLUP_WATCH;
+
+function serve() {
+ let server;
+
+ function toExit() {
+ if (server) server.kill(0);
+ }
+
+ return {
+ writeBundle() {
+ if (server) return;
+ server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], {
+ stdio: ['ignore', 'inherit', 'inherit'],
+ shell: true
+ });
+
+ process.on('SIGTERM', toExit);
+ process.on('exit', toExit);
+ }
+ };
+}
+
+export default {
+ input: 'src/main.js',
+ output: {
+ sourcemap: true,
+ format: 'iife',
+ name: 'app',
+ file: 'dist/bundle.js'
+ },
+ plugins: [
+ svelte({
+ compilerOptions: {
+ // enable run-time checks when not in production
+ dev: !production
+ }
+ }),
+ postcss({
+ minimize: true,
+ }),
+ // If you have external dependencies installed from
+ // npm, you'll most likely need these plugins. In
+ // some cases you'll need additional configuration -
+ // consult the documentation for details:
+ // https://github.com/rollup/plugins/tree/master/packages/commonjs
+ resolve({
+ browser: true,
+ dedupe: ['svelte']
+ }),
+ commonjs(),
+ copy({
+ targets: [
+ {src: 'src/index.html', dest: 'dist/'},
+ {src: 'src/global.css', dest: 'dist/'},
+ {src: 'src/assets', dest: 'dist/'},
+ ]
+ }),
+
+ // In dev mode, call `npm run start` once
+ // the bundle has been generated
+ !production && serve(),
+
+ // Watch the `dist` directory and refresh the
+ // browser on changes when not in production
+ !production && livereload('dist'),
+
+ // If we're building for production (npm run build
+ // instead of npm run dev), minify
+ production && terser()
+ ],
+ watch: {
+ clearScreen: false
+ }
+};
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates/svelte/frontend/scripts/setupTypeScript.js b/v2/cmd/wails/internal/commands/initialise/templates/templates/svelte/frontend/scripts/setupTypeScript.js
new file mode 100644
index 000000000..133658af1
--- /dev/null
+++ b/v2/cmd/wails/internal/commands/initialise/templates/templates/svelte/frontend/scripts/setupTypeScript.js
@@ -0,0 +1,121 @@
+// @ts-check
+
+/** This script modifies the project to support TS code in .svelte files like:
+
+
+
+ As well as validating the code for CI.
+ */
+
+/** To work on this script:
+ rm -rf test-template template && git clone sveltejs/template test-template && node scripts/setupTypeScript.js test-template
+*/
+
+const fs = require("fs")
+const path = require("path")
+const { argv } = require("process")
+
+const projectRoot = argv[2] || path.join(__dirname, "..")
+
+// Add deps to pkg.json
+const packageJSON = JSON.parse(fs.readFileSync(path.join(projectRoot, "package.json"), "utf8"))
+packageJSON.devDependencies = Object.assign(packageJSON.devDependencies, {
+ "svelte-check": "^2.0.0",
+ "svelte-preprocess": "^4.0.0",
+ "@rollup/plugin-typescript": "^8.0.0",
+ "typescript": "^4.0.0",
+ "tslib": "^2.0.0",
+ "@tsconfig/svelte": "^2.0.0"
+})
+
+// Add script for checking
+packageJSON.scripts = Object.assign(packageJSON.scripts, {
+ "check": "svelte-check --tsconfig ./tsconfig.json"
+})
+
+// Write the package JSON
+fs.writeFileSync(path.join(projectRoot, "package.json"), JSON.stringify(packageJSON, null, " "))
+
+// mv src/main.js to main.ts - note, we need to edit rollup.config.js for this too
+const beforeMainJSPath = path.join(projectRoot, "src", "main.js")
+const afterMainTSPath = path.join(projectRoot, "src", "main.ts")
+fs.renameSync(beforeMainJSPath, afterMainTSPath)
+
+// Switch the app.svelte file to use TS
+const appSveltePath = path.join(projectRoot, "src", "App.svelte")
+let appFile = fs.readFileSync(appSveltePath, "utf8")
+appFile = appFile.replace("
+
+
+
+
+
+ Greet
+
+ {#if greeting}
+ {greeting}
+ {/if}
+
+
+
\ No newline at end of file
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates/svelte/frontend/src/assets/fonts/OFL.txt b/v2/cmd/wails/internal/commands/initialise/templates/templates/svelte/frontend/src/assets/fonts/OFL.txt
new file mode 100644
index 000000000..bad763db1
--- /dev/null
+++ b/v2/cmd/wails/internal/commands/initialise/templates/templates/svelte/frontend/src/assets/fonts/OFL.txt
@@ -0,0 +1,93 @@
+Copyright 2016 The Nunito Project Authors (contact@sansoxygen.com),
+
+This Font Software is licensed under the SIL Open Font License, Version 1.1.
+This license is copied below, and is also available with a FAQ at:
+http://scripts.sil.org/OFL
+
+
+-----------------------------------------------------------
+SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
+-----------------------------------------------------------
+
+PREAMBLE
+The goals of the Open Font License (OFL) are to stimulate worldwide
+development of collaborative font projects, to support the font creation
+efforts of academic and linguistic communities, and to provide a free and
+open framework in which fonts may be shared and improved in partnership
+with others.
+
+The OFL allows the licensed fonts to be used, studied, modified and
+redistributed freely as long as they are not sold by themselves. The
+fonts, including any derivative works, can be bundled, embedded,
+redistributed and/or sold with any software provided that any reserved
+names are not used by derivative works. The fonts and derivatives,
+however, cannot be released under any other type of license. The
+requirement for fonts to remain under this license does not apply
+to any document created using the fonts or their derivatives.
+
+DEFINITIONS
+"Font Software" refers to the set of files released by the Copyright
+Holder(s) under this license and clearly marked as such. This may
+include source files, build scripts and documentation.
+
+"Reserved Font Name" refers to any names specified as such after the
+copyright statement(s).
+
+"Original Version" refers to the collection of Font Software components as
+distributed by the Copyright Holder(s).
+
+"Modified Version" refers to any derivative made by adding to, deleting,
+or substituting -- in part or in whole -- any of the components of the
+Original Version, by changing formats or by porting the Font Software to a
+new environment.
+
+"Author" refers to any designer, engineer, programmer, technical
+writer or other person who contributed to the Font Software.
+
+PERMISSION & CONDITIONS
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of the Font Software, to use, study, copy, merge, embed, modify,
+redistribute, and sell modified and unmodified copies of the Font
+Software, subject to the following conditions:
+
+1) Neither the Font Software nor any of its individual components,
+in Original or Modified Versions, may be sold by itself.
+
+2) Original or Modified Versions of the Font Software may be bundled,
+redistributed and/or sold with any software, provided that each copy
+contains the above copyright notice and this license. These can be
+included either as stand-alone text files, human-readable headers or
+in the appropriate machine-readable metadata fields within text or
+binary files as long as those fields can be easily viewed by the user.
+
+3) No Modified Version of the Font Software may use the Reserved Font
+Name(s) unless explicit written permission is granted by the corresponding
+Copyright Holder. This restriction only applies to the primary font name as
+presented to the users.
+
+4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
+Software shall not be used to promote, endorse or advertise any
+Modified Version, except to acknowledge the contribution(s) of the
+Copyright Holder(s) and the Author(s) or with their explicit written
+permission.
+
+5) The Font Software, modified or unmodified, in part or in whole,
+must be distributed entirely under this license, and must not be
+distributed under any other license. The requirement for fonts to
+remain under this license does not apply to any document created
+using the Font Software.
+
+TERMINATION
+This license becomes null and void if any of the above conditions are
+not met.
+
+DISCLAIMER
+THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
+COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
+DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
+OTHER DEALINGS IN THE FONT SOFTWARE.
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates/svelte/frontend/src/assets/fonts/nunito-v16-latin-regular.woff2 b/v2/cmd/wails/internal/commands/initialise/templates/templates/svelte/frontend/src/assets/fonts/nunito-v16-latin-regular.woff2
new file mode 100644
index 000000000..2f9cc5964
Binary files /dev/null and b/v2/cmd/wails/internal/commands/initialise/templates/templates/svelte/frontend/src/assets/fonts/nunito-v16-latin-regular.woff2 differ
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates/svelte/frontend/src/assets/images/logo-dark.svg b/v2/cmd/wails/internal/commands/initialise/templates/templates/svelte/frontend/src/assets/images/logo-dark.svg
new file mode 100644
index 000000000..66fa483c4
--- /dev/null
+++ b/v2/cmd/wails/internal/commands/initialise/templates/templates/svelte/frontend/src/assets/images/logo-dark.svg
@@ -0,0 +1,53 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates/svelte/frontend/src/global.css b/v2/cmd/wails/internal/commands/initialise/templates/templates/svelte/frontend/src/global.css
new file mode 100644
index 000000000..3827664ca
--- /dev/null
+++ b/v2/cmd/wails/internal/commands/initialise/templates/templates/svelte/frontend/src/global.css
@@ -0,0 +1,25 @@
+
+html {
+ text-align: center;
+ color: white;
+ background-color: rgba(0, 0, 0, 255);
+ width: 100%;
+ height: 100%;
+}
+
+body {
+ color: white;
+ font-family: 'Nunito', -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif;
+ margin: 0;
+ width: 100%;
+ height: 100%;
+ overscroll-behavior: none;
+}
+
+@font-face {
+ font-family: 'Nunito';
+ font-style: normal;
+ font-weight: 400;
+ src: local(''),
+ url('./assets/fonts/nunito-v16-latin-regular.woff2') format('woff2')
+}
\ No newline at end of file
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates/svelte/frontend/src/index.tmpl.html b/v2/cmd/wails/internal/commands/initialise/templates/templates/svelte/frontend/src/index.tmpl.html
new file mode 100644
index 000000000..d6dfa7948
--- /dev/null
+++ b/v2/cmd/wails/internal/commands/initialise/templates/templates/svelte/frontend/src/index.tmpl.html
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+ {{.ProjectName}}
+
+
+
+
+
+
+
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates/svelte/frontend/src/main.js b/v2/cmd/wails/internal/commands/initialise/templates/templates/svelte/frontend/src/main.js
new file mode 100644
index 000000000..d80e9a350
--- /dev/null
+++ b/v2/cmd/wails/internal/commands/initialise/templates/templates/svelte/frontend/src/main.js
@@ -0,0 +1,7 @@
+import App from './App.svelte';
+
+const app = new App({
+ target: document.body,
+});
+
+export default app;
\ No newline at end of file
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates/svelte/gitignore.txt b/v2/cmd/wails/internal/commands/initialise/templates/templates/svelte/gitignore.txt
new file mode 100644
index 000000000..da44b7c53
--- /dev/null
+++ b/v2/cmd/wails/internal/commands/initialise/templates/templates/svelte/gitignore.txt
@@ -0,0 +1,9 @@
+# Wails bin directory
+build/bin
+
+# IDEs
+.idea
+.vscode
+
+# The black hole that is...
+node_modules
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates/svelte/go.mod.tmpl b/v2/cmd/wails/internal/commands/initialise/templates/templates/svelte/go.mod.tmpl
new file mode 100644
index 000000000..2c68d66ed
--- /dev/null
+++ b/v2/cmd/wails/internal/commands/initialise/templates/templates/svelte/go.mod.tmpl
@@ -0,0 +1,38 @@
+module changeme
+
+go 1.17
+
+require github.com/wailsapp/wails/v2 {{.WailsVersion}}
+
+require (
+github.com/andybalholm/brotli v1.0.2 // indirect
+github.com/davecgh/go-spew v1.1.1 // indirect
+github.com/fasthttp/websocket v0.0.0-20200320073529-1554a54587ab // indirect
+github.com/gabriel-vasile/mimetype v1.3.1 // indirect
+github.com/go-ole/go-ole v1.2.5 // indirect
+github.com/gofiber/fiber/v2 v2.17.0 // indirect
+github.com/gofiber/websocket/v2 v2.0.8 // indirect
+github.com/google/uuid v1.1.2 // indirect
+github.com/imdario/mergo v0.3.12 // indirect
+github.com/jchv/go-winloader v0.0.0-20200815041850-dec1ee9a7fd5 // indirect
+github.com/klauspost/compress v1.12.2 // indirect
+github.com/leaanthony/debme v1.2.1 // indirect
+github.com/leaanthony/go-ansi-parser v1.0.1 // indirect
+github.com/leaanthony/go-common-file-dialog v1.0.3 // indirect
+github.com/leaanthony/go-webview2 v0.0.0-20210914103035-f00aa774a934 // indirect
+github.com/leaanthony/slicer v1.5.0 // indirect
+github.com/leaanthony/typescriptify-golang-structs v0.1.7 // indirect
+github.com/leaanthony/webview2runtime v1.1.0 // indirect
+github.com/leaanthony/winc v0.0.0-20210921073452-54963136bf18 // indirect
+github.com/pkg/browser v0.0.0-20210706143420-7d21f8c997e2 // indirect
+github.com/pkg/errors v0.9.1 // indirect
+github.com/savsgio/gotils v0.0.0-20200117113501-90175b0fbe3f // indirect
+github.com/tkrajina/go-reflector v0.5.5 // indirect
+github.com/valyala/bytebufferpool v1.0.0 // indirect
+github.com/valyala/fasthttp v1.28.0 // indirect
+github.com/valyala/tcplisten v1.0.0 // indirect
+golang.org/x/net v0.0.0-20210510120150-4163338589ed // indirect
+golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf // indirect
+)
+
+// replace github.com/wailsapp/wails/v2 {{.WailsVersion}} => {{.WailsDirectory}}
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates/svelte/go.sum b/v2/cmd/wails/internal/commands/initialise/templates/templates/svelte/go.sum
new file mode 100644
index 000000000..575af8230
--- /dev/null
+++ b/v2/cmd/wails/internal/commands/initialise/templates/templates/svelte/go.sum
@@ -0,0 +1,228 @@
+github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y=
+github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA=
+github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0=
+github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs=
+github.com/andybalholm/brotli v1.0.2 h1:JKnhI/XQ75uFBTiuzXpzFrUriDPiZjlOSzh6wXogP0E=
+github.com/andybalholm/brotli v1.0.2/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y=
+github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
+github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
+github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
+github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
+github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o=
+github.com/fasthttp/websocket v0.0.0-20200320073529-1554a54587ab h1:9e2joQGp642wHGFP5m86SDptAavrdGBe8/x9DGEEAaI=
+github.com/fasthttp/websocket v0.0.0-20200320073529-1554a54587ab/go.mod h1:smsv/h4PBEBaU0XDTY5UwJTpZv69fQ0FfcLJr21mA6Y=
+github.com/fatih/structtag v1.2.0/go.mod h1:mBJUNpUnHmRKrKlQQlmCrh5PuhftFbNv8Ys4/aAZl94=
+github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
+github.com/flytam/filenamify v1.0.0/go.mod h1:Dzf9kVycwcsBlr2ATg6uxjqiFgKGH+5SKFuhdeP5zu8=
+github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
+github.com/gabriel-vasile/mimetype v1.3.1 h1:qevA6c2MtE1RorlScnixeG0VA1H4xrXyhyX3oWBynNQ=
+github.com/gabriel-vasile/mimetype v1.3.1/go.mod h1:fA8fi6KUiG7MgQQ+mEWotXoEOvmxRtOJlERCzSmRvr8=
+github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
+github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M=
+github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
+github.com/go-git/gcfg v1.5.0/go.mod h1:5m20vg6GwYabIxaOonVkTdrILxQMpEShl1xiMF4ua+E=
+github.com/go-git/go-billy/v5 v5.0.0/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0=
+github.com/go-git/go-billy/v5 v5.1.0/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0=
+github.com/go-git/go-billy/v5 v5.2.0/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0=
+github.com/go-git/go-git-fixtures/v4 v4.0.2-0.20200613231340-f56387b50c12/go.mod h1:m+ICp2rF3jDhFgEZ/8yziagdT1C+ZpZcrJjappBCDSw=
+github.com/go-git/go-git/v5 v5.3.0/go.mod h1:xdX4bWJ48aOrdhnl2XqHYstHbbp6+LFS4r4X+lNVprw=
+github.com/go-ole/go-ole v1.2.4/go.mod h1:XCwSNxSkXRo4vlyPy93sltvi/qJq0jqQhjqQNIwKuxM=
+github.com/go-ole/go-ole v1.2.5 h1:t4MGB5xEDZvXI+0rMjjsfBsD7yAgp/s9ZDkL1JndXwY=
+github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
+github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
+github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
+github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
+github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI=
+github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo=
+github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw=
+github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM=
+github.com/gofiber/fiber/v2 v2.17.0 h1:qP3PkGUbBB0i9iQh5E057XI1yO5CZigUxZhyUFYAFoM=
+github.com/gofiber/fiber/v2 v2.17.0/go.mod h1:iftruuHGkRYGEXVISmdD7HTYWyfS2Bh+Dkfq4n/1Owg=
+github.com/gofiber/websocket/v2 v2.0.8 h1:Hb4y6IxYZVMO0segROODXJiXVgVD3a6i7wnfot8kM6k=
+github.com/gofiber/websocket/v2 v2.0.8/go.mod h1:fv8HSGQX09sauNv9g5Xq8GeGAaahLFYQKKb4ZdT0x2w=
+github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
+github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
+github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
+github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
+github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
+github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
+github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
+github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y=
+github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
+github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU=
+github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
+github.com/jackmordaunt/icns v1.0.0/go.mod h1:7TTQVEuGzVVfOPPlLNHJIkzA6CoV7aH1Dv9dW351oOo=
+github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
+github.com/jchv/go-winloader v0.0.0-20200815041850-dec1ee9a7fd5/go.mod h1:alcuEEnZsY1WQsagKhZDsoPCRoOijYqhZvPwLG0kzVs=
+github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e h1:Q3+PugElBCf4PFpxhErSzU3/PY5sFL5Z6rfv4AbGAck=
+github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e/go.mod h1:alcuEEnZsY1WQsagKhZDsoPCRoOijYqhZvPwLG0kzVs=
+github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4=
+github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
+github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
+github.com/klauspost/compress v1.8.2/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
+github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
+github.com/klauspost/compress v1.12.2 h1:2KCfW3I9M7nSc5wOqXAlW2v2U6v+w6cbjvbfp+OykW8=
+github.com/klauspost/compress v1.12.2/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg=
+github.com/klauspost/cpuid v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
+github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
+github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
+github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
+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.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
+github.com/leaanthony/clir v1.0.4/go.mod h1:k/RBkdkFl18xkkACMCLt09bhiZnrGORoxmomeMvDpE0=
+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/go-ansi-parser v1.0.1 h1:97v6c5kYppVsbScf4r/VZdXyQ21KQIfeQOk2DgKxGG4=
+github.com/leaanthony/go-ansi-parser v1.0.1/go.mod h1:7arTzgVI47srICYhvgUV4CGd063sGEeoSlych5yeSPM=
+github.com/leaanthony/go-common-file-dialog v1.0.3 h1:O0uGjKnWtdEADGrkg+TyAAbZylykMwwx/MNEXn9fp+Y=
+github.com/leaanthony/go-common-file-dialog v1.0.3/go.mod h1:TGhEc9eSJgRsupZ+iH1ZgAOnEo9zp05cRH2j08RPrF0=
+github.com/leaanthony/go-webview2 v0.0.0-20210928094513-a94a08b538bd h1:6m4zZ/esiByaDbzgdvDxjsOaIDgtuG1q2cyhjAi6uAg=
+github.com/leaanthony/go-webview2 v0.0.0-20210928094513-a94a08b538bd/go.mod h1:lS5ds4bruPk9d7lzdF/OH31Z0YCerI6MmHNFGsWoUnM=
+github.com/leaanthony/gosod v1.0.3/go.mod h1:BJ2J+oHsQIyIQpnLPjnqFGTMnOZXDbvWtRCSG7jGxs4=
+github.com/leaanthony/idgen v1.0.0/go.mod h1:4nBZnt8ml/f/ic/EVQuLxuj817RccT2fyrUaZFxrcVA=
+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/typescriptify-golang-structs v0.1.7 h1:yoznzWzyxkO/iWdlpq+aPcuJ5Y/hpjq/lmgMFmpjwl0=
+github.com/leaanthony/typescriptify-golang-structs v0.1.7/go.mod h1:cWtOkiVhMF77e6phAXUcfNwYmMwCJ67Sij24lfvi9Js=
+github.com/leaanthony/webview2runtime v1.1.0 h1:N0pv55ift8XtqozIp4PNOtRCJ/Qdd/qzx80lUpalS4c=
+github.com/leaanthony/webview2runtime v1.1.0/go.mod h1:hH9GnWCve3DYzNaPOcPbhHQ7fodXR1QJNsnwixid4Tk=
+github.com/leaanthony/winc v0.0.0-20210921073452-54963136bf18 h1:5iOd93PZbpH4Iir8QkC4coFD+zEQEZSIRcjwjTFZkr0=
+github.com/leaanthony/winc v0.0.0-20210921073452-54963136bf18/go.mod h1:KEbMsKoznsebyGHwLk5LqkFOxL5uXSRdvpP4+avmAMs=
+github.com/leaanthony/winicon v1.0.0/go.mod h1:en5xhijl92aphrJdmRPlh4NI1L6wq3gEm0LpXAPghjU=
+github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
+github.com/logrusorgru/aurora v0.0.0-20181002194514-a7b3b318ed4e/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4=
+github.com/matryer/is v1.4.0 h1:sosSmIWwkYITGrxZ25ULNDeKiMNzFSr4V/eqBQP0PeE=
+github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU=
+github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
+github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
+github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
+github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
+github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
+github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8=
+github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
+github.com/olekukonko/tablewriter v0.0.4/go.mod h1:zq6QwlOf5SlnkVbMSr5EoBv3636FWnp+qbPhuoO21uA=
+github.com/pkg/browser v0.0.0-20210706143420-7d21f8c997e2 h1:acNfDZXmm28D2Yg/c3ALnZStzNaZMSagpbr96vY6Zjc=
+github.com/pkg/browser v0.0.0-20210706143420-7d21f8c997e2/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI=
+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/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/savsgio/gotils v0.0.0-20200117113501-90175b0fbe3f h1:PgA+Olipyj258EIEYnpFFONrrCcAIWNUNoFhUfMqAGY=
+github.com/savsgio/gotils v0.0.0-20200117113501-90175b0fbe3f/go.mod h1:lHhJedqxCoHN+zMtwGNTXWmF0u9Jt363FYRhV6g0CdY=
+github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
+github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
+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/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
+github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
+github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
+github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
+github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/tc-hib/winres v0.1.5/go.mod h1:pe6dOR40VOrGz8PkzreVKNvEKnlE8t4yR8A8naL+t7A=
+github.com/tdewolff/minify v2.3.6+incompatible/go.mod h1:9Ov578KJUmAWpS6NeZwRZyT56Uf6o3Mcz9CEsg8USYs=
+github.com/tdewolff/parse v2.3.4+incompatible/go.mod h1:8oBwCsVmUkgHO8M5iCzSIDtpzXOT0WXX9cWhz+bIzJQ=
+github.com/tdewolff/test v1.0.6/go.mod h1:6DAvZliBAAnD7rhVgwaM7DE5/d9NMOAJ09SqYqeK4QE=
+github.com/tidwall/gjson v1.8.0/go.mod h1:5/xDoumyyDNerp2U36lyolv46b3uF/9Bu6OfyQ9GImk=
+github.com/tidwall/match v1.0.3/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
+github.com/tidwall/pretty v1.1.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
+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.5/go.mod h1:ECbqLgccecY5kPmPmXg1MrHW585yMcDkVl6IvJe64T4=
+github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
+github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
+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/fasthttp v1.9.0/go.mod h1:FstJa9V+Pj9vQ7OJie2qMHdwemEDaDiSdBnvPM1Su9w=
+github.com/valyala/fasthttp v1.26.0/go.mod h1:cmWIqlu99AO/RKcp1HWaViTqc57FswJOfYYdPJBl8BA=
+github.com/valyala/fasthttp v1.28.0 h1:ruVmTmZaBR5i67NqnjvvH5gEv0zwHfWtbjoyW98iho4=
+github.com/valyala/fasthttp v1.28.0/go.mod h1:cmWIqlu99AO/RKcp1HWaViTqc57FswJOfYYdPJBl8BA=
+github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio=
+github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8=
+github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc=
+github.com/wailsapp/wails/v2 v2.0.0-beta.3 h1:8vhBbnjpYDF6cCUwKadon7J/98UjcP1nrnptUl70Tfg=
+github.com/wailsapp/wails/v2 v2.0.0-beta.3/go.mod h1:aku28riyHF2G5jmx/qtxjLWi7VwpTjhhX/HVLCptWFA=
+github.com/wzshiming/ctc v1.2.3/go.mod h1:2tVAtIY7SUyraSk0JxvwmONNPFL4ARavPuEsg5+KA28=
+github.com/wzshiming/winseq v0.0.0-20200112104235-db357dc107ae/go.mod h1:VTAq37rkGeV+WOybvZwjXiJOicICdpLCN8ifpISjK20=
+github.com/xanzy/ssh-agent v0.3.0/go.mod h1:3s9xbODqPuuhK9JV1R321M/FlMZSBvE5aY6eAcqrDh0=
+github.com/xyproto/xpm v1.2.1/go.mod h1:cMnesLsD0PBXLgjDfTDEaKr8XyTFsnP1QycSqRw7BiY=
+github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
+github.com/ztrue/tracerr v0.3.0/go.mod h1:qEalzze4VN9O8tnhBXScfCrmoJo10o8TN5ciKjm6Mww=
+golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
+golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
+golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
+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/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
+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-20210505024714-0287a6fb4125/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
+golang.org/x/net v0.0.0-20210510120150-4163338589ed h1:p9UgmWI9wKpfYmgaV/IZKGdXc5qEK45tDwwwDyjS26I=
+golang.org/x/net v0.0.0-20210510120150-4163338589ed/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
+golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+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-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200107162124-548cf772de50/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200810151505-1b9f1253b3ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20210611083646-a4fc73990273/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6 h1:foEbQz/B0Oz6YIqu/69kfXPYeFQAuuMYFkjaqXzl5Wo=
+golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
+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/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
+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.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
+golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/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=
+google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
+google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
+gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
+gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
+gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
+gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+nhooyr.io/websocket v1.8.6/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0=
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates/svelte/main.tmpl.go b/v2/cmd/wails/internal/commands/initialise/templates/templates/svelte/main.tmpl.go
new file mode 100644
index 000000000..89a4cecbb
--- /dev/null
+++ b/v2/cmd/wails/internal/commands/initialise/templates/templates/svelte/main.tmpl.go
@@ -0,0 +1,54 @@
+package main
+
+import (
+ "embed"
+ "log"
+
+ "github.com/wailsapp/wails/v2"
+ "github.com/wailsapp/wails/v2/pkg/logger"
+ "github.com/wailsapp/wails/v2/pkg/options"
+ "github.com/wailsapp/wails/v2/pkg/options/windows"
+)
+
+//go:embed frontend/dist
+var assets embed.FS
+
+func main() {
+ // Create an instance of the app structure
+ app := NewApp()
+
+ // Create application with options
+ err := wails.Run(&options.App{
+ Title: "{{.ProjectName}}",
+ Width: 720,
+ Height: 570,
+ MinWidth: 720,
+ MinHeight: 570,
+ MaxWidth: 1280,
+ MaxHeight: 740,
+ DisableResize: false,
+ Fullscreen: false,
+ Frameless: false,
+ StartHidden: false,
+ HideWindowOnClose: false,
+ RGBA: &options.RGBA{R: 255, G: 255, B: 255, A: 255},
+ Assets: assets,
+ LogLevel: logger.DEBUG,
+ OnStartup: app.startup,
+ OnDomReady: app.domReady,
+ OnShutdown: app.shutdown,
+ Bind: []interface{}{
+ app,
+ },
+ // Windows platform specific options
+ Windows: &windows.Options{
+ WebviewIsTransparent: false,
+ WindowIsTranslucent: false,
+ DisableWindowIcon: false,
+ },
+ })
+
+ if err != nil {
+ log.Fatal(err)
+ }
+}
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates/svelte/template.json b/v2/cmd/wails/internal/commands/initialise/templates/templates/svelte/template.json
new file mode 100644
index 000000000..f04858241
--- /dev/null
+++ b/v2/cmd/wails/internal/commands/initialise/templates/templates/svelte/template.json
@@ -0,0 +1,7 @@
+{
+ "name": "Basic Svelte + Rollup",
+ "shortname": "svelte",
+ "author": "Lea Anthony ",
+ "description": "Svelte template using rollup to bundle css, images and fonts",
+ "helpurl": "https://github.com/wailsapp/wails"
+}
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates/svelte/wails.tmpl.json b/v2/cmd/wails/internal/commands/initialise/templates/templates/svelte/wails.tmpl.json
new file mode 100644
index 000000000..b8d08108d
--- /dev/null
+++ b/v2/cmd/wails/internal/commands/initialise/templates/templates/svelte/wails.tmpl.json
@@ -0,0 +1,11 @@
+{
+ "name": "{{.ProjectName}}",
+ "outputfilename": "{{.BinaryName}}",
+ "assetdir": "frontend/dist",
+ "frontend:install": "npm install",
+ "frontend:build": "npm run build",
+ "author": {
+ "name": "{{.AuthorName}}",
+ "email": "{{.AuthorEmail}}"
+ }
+}
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates/vanilla/README.md b/v2/cmd/wails/internal/commands/initialise/templates/templates/vanilla/README.md
new file mode 100644
index 000000000..5b2db9baf
--- /dev/null
+++ b/v2/cmd/wails/internal/commands/initialise/templates/templates/vanilla/README.md
@@ -0,0 +1,15 @@
+# README
+
+## About
+
+This template uses vanilla JS / HTML and CSS.
+
+## Live Development
+
+To run in live development mode, run `wails dev` in the project directory. The frontend dev server will run
+on http://localhost:34115. Open this in your browser to connect to your application.
+
+## Building
+
+For a production build, use `wails build`.
+
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates/vanilla/app.go b/v2/cmd/wails/internal/commands/initialise/templates/templates/vanilla/app.go
new file mode 100644
index 000000000..d04d123d4
--- /dev/null
+++ b/v2/cmd/wails/internal/commands/initialise/templates/templates/vanilla/app.go
@@ -0,0 +1,37 @@
+package main
+
+import (
+ "context"
+ "fmt"
+)
+
+// App struct
+type App struct {
+ ctx context.Context
+}
+
+// NewApp creates a new App application struct
+func NewApp() *App {
+ return &App{}
+}
+
+// startup is called at application startup
+func (b *App) startup(ctx context.Context) {
+ // Perform your setup here
+ b.ctx = ctx
+}
+
+// domReady is called after the front-end dom has been loaded
+func (b *App) domReady(ctx context.Context) {
+ // Add your action here
+}
+
+// shutdown is called at application termination
+func (b *App) shutdown(ctx context.Context) {
+ // Perform your teardown here
+}
+
+// Greet returns a greeting for the given name
+func (b *App) Greet(name string) string {
+ return fmt.Sprintf("Hello %s, It's show time!", name)
+}
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates/vanilla/frontend/src/assets/fonts/OFL.txt b/v2/cmd/wails/internal/commands/initialise/templates/templates/vanilla/frontend/src/assets/fonts/OFL.txt
new file mode 100644
index 000000000..9cac04ce8
--- /dev/null
+++ b/v2/cmd/wails/internal/commands/initialise/templates/templates/vanilla/frontend/src/assets/fonts/OFL.txt
@@ -0,0 +1,93 @@
+Copyright 2016 The Nunito Project Authors (contact@sansoxygen.com),
+
+This Font Software is licensed under the SIL Open Font License, Version 1.1.
+This license is copied below, and is also available with a FAQ at:
+http://scripts.sil.org/OFL
+
+
+-----------------------------------------------------------
+SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
+-----------------------------------------------------------
+
+PREAMBLE
+The goals of the Open Font License (OFL) are to stimulate worldwide
+development of collaborative font projects, to support the font creation
+efforts of academic and linguistic communities, and to provide a free and
+open framework in which fonts may be shared and improved in partnership
+with others.
+
+The OFL allows the licensed fonts to be used, studied, modified and
+redistributed freely as long as they are not sold by themselves. The
+fonts, including any derivative works, can be bundled, embedded,
+redistributed and/or sold with any software provided that any reserved
+names are not used by derivative works. The fonts and derivatives,
+however, cannot be released under any other type of license. The
+requirement for fonts to remain under this license does not apply
+to any document created using the fonts or their derivatives.
+
+DEFINITIONS
+"Font Software" refers to the set of files released by the Copyright
+Holder(s) under this license and clearly marked as such. This may
+include source files, build scripts and documentation.
+
+"Reserved Font Name" refers to any names specified as such after the
+copyright statement(s).
+
+"Original Version" refers to the collection of Font Software components as
+distributed by the Copyright Holder(s).
+
+"Modified Version" refers to any derivative made by adding to, deleting,
+or substituting -- in part or in whole -- any of the components of the
+Original Version, by changing formats or by porting the Font Software to a
+new environment.
+
+"Author" refers to any designer, engineer, programmer, technical
+writer or other person who contributed to the Font Software.
+
+PERMISSION & CONDITIONS
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of the Font Software, to use, study, copy, merge, embed, modify,
+redistribute, and sell modified and unmodified copies of the Font
+Software, subject to the following conditions:
+
+1) Neither the Font Software nor any of its individual components,
+in Original or Modified Versions, may be sold by itself.
+
+2) Original or Modified Versions of the Font Software may be bundled,
+redistributed and/or sold with any software, provided that each copy
+contains the above copyright notice and this license. These can be
+included either as stand-alone text files, human-readable headers or
+in the appropriate machine-readable metadata fields within text or
+binary files as long as those fields can be easily viewed by the user.
+
+3) No Modified Version of the Font Software may use the Reserved Font
+Name(s) unless explicit written permission is granted by the corresponding
+Copyright Holder. This restriction only applies to the primary font name as
+presented to the users.
+
+4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
+Software shall not be used to promote, endorse or advertise any
+Modified Version, except to acknowledge the contribution(s) of the
+Copyright Holder(s) and the Author(s) or with their explicit written
+permission.
+
+5) The Font Software, modified or unmodified, in part or in whole,
+must be distributed entirely under this license, and must not be
+distributed under any other license. The requirement for fonts to
+remain under this license does not apply to any document created
+using the Font Software.
+
+TERMINATION
+This license becomes null and void if any of the above conditions are
+not met.
+
+DISCLAIMER
+THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
+COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
+DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
+OTHER DEALINGS IN THE FONT SOFTWARE.
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates/vanilla/frontend/src/assets/fonts/nunito-v16-latin-regular.woff2 b/v2/cmd/wails/internal/commands/initialise/templates/templates/vanilla/frontend/src/assets/fonts/nunito-v16-latin-regular.woff2
new file mode 100644
index 000000000..2f9cc5964
Binary files /dev/null and b/v2/cmd/wails/internal/commands/initialise/templates/templates/vanilla/frontend/src/assets/fonts/nunito-v16-latin-regular.woff2 differ
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates/vanilla/frontend/src/assets/images/logo-dark.svg b/v2/cmd/wails/internal/commands/initialise/templates/templates/vanilla/frontend/src/assets/images/logo-dark.svg
new file mode 100644
index 000000000..855d7e0ef
--- /dev/null
+++ b/v2/cmd/wails/internal/commands/initialise/templates/templates/vanilla/frontend/src/assets/images/logo-dark.svg
@@ -0,0 +1,80 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates/vanilla/frontend/src/index.tmpl.html b/v2/cmd/wails/internal/commands/initialise/templates/templates/vanilla/frontend/src/index.tmpl.html
new file mode 100644
index 000000000..73eebf442
--- /dev/null
+++ b/v2/cmd/wails/internal/commands/initialise/templates/templates/vanilla/frontend/src/index.tmpl.html
@@ -0,0 +1,19 @@
+
+
+
+ {{.ProjectName}}
+
+
+
+
+
+ Please enter your name below 👇
+
+
+ Greet
+
+
+
+
+
+
\ No newline at end of file
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates/vanilla/frontend/src/main.css b/v2/cmd/wails/internal/commands/initialise/templates/templates/vanilla/frontend/src/main.css
new file mode 100644
index 000000000..1a73a0da8
--- /dev/null
+++ b/v2/cmd/wails/internal/commands/initialise/templates/templates/vanilla/frontend/src/main.css
@@ -0,0 +1,73 @@
+html {
+ background-color: rgba(33, 37, 43, 1);
+ text-align: center;
+ color: white;
+}
+
+body {
+ margin: 0;
+ color: white;
+ font-family: "Nunito", -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto",
+ "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue",
+ sans-serif;
+ overscroll-behavior: none;
+}
+
+@font-face {
+ font-family: "Nunito";
+ font-style: normal;
+ font-weight: 400;
+ src: local(""),
+ url("assets/fonts/nunito-v16-latin-regular.woff2") format("woff2");
+}
+
+.logo {
+ display: block;
+ width: 35%;
+ height: 35%;
+ margin: auto;
+ padding: 15% 0 0;
+ background-position: center;
+ background-repeat: no-repeat;
+ background-image: url("./assets/images/logo-dark.svg");
+}
+.result {
+ height: 20px;
+ line-height: 20px;
+ margin: 1.5rem auto;
+}
+.input-box .btn {
+ width: 60px;
+ height: 30px;
+ line-height: 30px;
+ border-radius: 3px;
+ border: none;
+ margin: 0 0 0 20px;
+ padding: 0 8px;
+ cursor: pointer;
+}
+.input-box .btn:hover {
+ background-image: linear-gradient(to top, #cfd9df 0%, #e2ebf0 100%);
+ color: #333333;
+}
+
+.input-box .input {
+ border: none;
+ border-radius: 3px;
+ outline: none;
+ height: 30px;
+ line-height: 30px;
+ padding: 0 10px;
+ background-color: rgba(240, 240, 240, 1);
+ -webkit-font-smoothing: antialiased;
+}
+
+.input-box .input:hover {
+ border: none;
+ background-color: rgba(255, 255, 255, 1);
+}
+
+.input-box .input:focus {
+ border: none;
+ background-color: rgba(255, 255, 255, 1);
+}
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates/vanilla/frontend/src/main.js b/v2/cmd/wails/internal/commands/initialise/templates/templates/vanilla/frontend/src/main.js
new file mode 100644
index 000000000..db404e459
--- /dev/null
+++ b/v2/cmd/wails/internal/commands/initialise/templates/templates/vanilla/frontend/src/main.js
@@ -0,0 +1,23 @@
+// Get input + focus
+let nameElement = document.getElementById("name");
+nameElement.focus();
+
+// Setup the greet function
+window.greet = function () {
+
+ // Get name
+ let name = nameElement.value;
+
+ // Call App.Greet(name)
+ window.go.main.App.Greet(name).then((result) => {
+ // Update result with data back from App.Greet()
+ document.getElementById("result").innerText = result;
+ });
+};
+
+nameElement.onkeydown = function (e) {
+ console.log(e)
+ if (e.keyCode == 13) {
+ window.greet()
+ }
+}
\ No newline at end of file
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates/vanilla/gitignore.txt b/v2/cmd/wails/internal/commands/initialise/templates/templates/vanilla/gitignore.txt
new file mode 100644
index 000000000..da44b7c53
--- /dev/null
+++ b/v2/cmd/wails/internal/commands/initialise/templates/templates/vanilla/gitignore.txt
@@ -0,0 +1,9 @@
+# Wails bin directory
+build/bin
+
+# IDEs
+.idea
+.vscode
+
+# The black hole that is...
+node_modules
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates/vanilla/go.mod.tmpl b/v2/cmd/wails/internal/commands/initialise/templates/templates/vanilla/go.mod.tmpl
new file mode 100644
index 000000000..2c68d66ed
--- /dev/null
+++ b/v2/cmd/wails/internal/commands/initialise/templates/templates/vanilla/go.mod.tmpl
@@ -0,0 +1,38 @@
+module changeme
+
+go 1.17
+
+require github.com/wailsapp/wails/v2 {{.WailsVersion}}
+
+require (
+github.com/andybalholm/brotli v1.0.2 // indirect
+github.com/davecgh/go-spew v1.1.1 // indirect
+github.com/fasthttp/websocket v0.0.0-20200320073529-1554a54587ab // indirect
+github.com/gabriel-vasile/mimetype v1.3.1 // indirect
+github.com/go-ole/go-ole v1.2.5 // indirect
+github.com/gofiber/fiber/v2 v2.17.0 // indirect
+github.com/gofiber/websocket/v2 v2.0.8 // indirect
+github.com/google/uuid v1.1.2 // indirect
+github.com/imdario/mergo v0.3.12 // indirect
+github.com/jchv/go-winloader v0.0.0-20200815041850-dec1ee9a7fd5 // indirect
+github.com/klauspost/compress v1.12.2 // indirect
+github.com/leaanthony/debme v1.2.1 // indirect
+github.com/leaanthony/go-ansi-parser v1.0.1 // indirect
+github.com/leaanthony/go-common-file-dialog v1.0.3 // indirect
+github.com/leaanthony/go-webview2 v0.0.0-20210914103035-f00aa774a934 // indirect
+github.com/leaanthony/slicer v1.5.0 // indirect
+github.com/leaanthony/typescriptify-golang-structs v0.1.7 // indirect
+github.com/leaanthony/webview2runtime v1.1.0 // indirect
+github.com/leaanthony/winc v0.0.0-20210921073452-54963136bf18 // indirect
+github.com/pkg/browser v0.0.0-20210706143420-7d21f8c997e2 // indirect
+github.com/pkg/errors v0.9.1 // indirect
+github.com/savsgio/gotils v0.0.0-20200117113501-90175b0fbe3f // indirect
+github.com/tkrajina/go-reflector v0.5.5 // indirect
+github.com/valyala/bytebufferpool v1.0.0 // indirect
+github.com/valyala/fasthttp v1.28.0 // indirect
+github.com/valyala/tcplisten v1.0.0 // indirect
+golang.org/x/net v0.0.0-20210510120150-4163338589ed // indirect
+golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf // indirect
+)
+
+// replace github.com/wailsapp/wails/v2 {{.WailsVersion}} => {{.WailsDirectory}}
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates/vanilla/go.sum b/v2/cmd/wails/internal/commands/initialise/templates/templates/vanilla/go.sum
new file mode 100644
index 000000000..575af8230
--- /dev/null
+++ b/v2/cmd/wails/internal/commands/initialise/templates/templates/vanilla/go.sum
@@ -0,0 +1,228 @@
+github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y=
+github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA=
+github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0=
+github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs=
+github.com/andybalholm/brotli v1.0.2 h1:JKnhI/XQ75uFBTiuzXpzFrUriDPiZjlOSzh6wXogP0E=
+github.com/andybalholm/brotli v1.0.2/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y=
+github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
+github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
+github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
+github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
+github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o=
+github.com/fasthttp/websocket v0.0.0-20200320073529-1554a54587ab h1:9e2joQGp642wHGFP5m86SDptAavrdGBe8/x9DGEEAaI=
+github.com/fasthttp/websocket v0.0.0-20200320073529-1554a54587ab/go.mod h1:smsv/h4PBEBaU0XDTY5UwJTpZv69fQ0FfcLJr21mA6Y=
+github.com/fatih/structtag v1.2.0/go.mod h1:mBJUNpUnHmRKrKlQQlmCrh5PuhftFbNv8Ys4/aAZl94=
+github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
+github.com/flytam/filenamify v1.0.0/go.mod h1:Dzf9kVycwcsBlr2ATg6uxjqiFgKGH+5SKFuhdeP5zu8=
+github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
+github.com/gabriel-vasile/mimetype v1.3.1 h1:qevA6c2MtE1RorlScnixeG0VA1H4xrXyhyX3oWBynNQ=
+github.com/gabriel-vasile/mimetype v1.3.1/go.mod h1:fA8fi6KUiG7MgQQ+mEWotXoEOvmxRtOJlERCzSmRvr8=
+github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
+github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M=
+github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
+github.com/go-git/gcfg v1.5.0/go.mod h1:5m20vg6GwYabIxaOonVkTdrILxQMpEShl1xiMF4ua+E=
+github.com/go-git/go-billy/v5 v5.0.0/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0=
+github.com/go-git/go-billy/v5 v5.1.0/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0=
+github.com/go-git/go-billy/v5 v5.2.0/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0=
+github.com/go-git/go-git-fixtures/v4 v4.0.2-0.20200613231340-f56387b50c12/go.mod h1:m+ICp2rF3jDhFgEZ/8yziagdT1C+ZpZcrJjappBCDSw=
+github.com/go-git/go-git/v5 v5.3.0/go.mod h1:xdX4bWJ48aOrdhnl2XqHYstHbbp6+LFS4r4X+lNVprw=
+github.com/go-ole/go-ole v1.2.4/go.mod h1:XCwSNxSkXRo4vlyPy93sltvi/qJq0jqQhjqQNIwKuxM=
+github.com/go-ole/go-ole v1.2.5 h1:t4MGB5xEDZvXI+0rMjjsfBsD7yAgp/s9ZDkL1JndXwY=
+github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
+github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
+github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
+github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
+github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI=
+github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo=
+github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw=
+github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM=
+github.com/gofiber/fiber/v2 v2.17.0 h1:qP3PkGUbBB0i9iQh5E057XI1yO5CZigUxZhyUFYAFoM=
+github.com/gofiber/fiber/v2 v2.17.0/go.mod h1:iftruuHGkRYGEXVISmdD7HTYWyfS2Bh+Dkfq4n/1Owg=
+github.com/gofiber/websocket/v2 v2.0.8 h1:Hb4y6IxYZVMO0segROODXJiXVgVD3a6i7wnfot8kM6k=
+github.com/gofiber/websocket/v2 v2.0.8/go.mod h1:fv8HSGQX09sauNv9g5Xq8GeGAaahLFYQKKb4ZdT0x2w=
+github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
+github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
+github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
+github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
+github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
+github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
+github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
+github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y=
+github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
+github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU=
+github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
+github.com/jackmordaunt/icns v1.0.0/go.mod h1:7TTQVEuGzVVfOPPlLNHJIkzA6CoV7aH1Dv9dW351oOo=
+github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
+github.com/jchv/go-winloader v0.0.0-20200815041850-dec1ee9a7fd5/go.mod h1:alcuEEnZsY1WQsagKhZDsoPCRoOijYqhZvPwLG0kzVs=
+github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e h1:Q3+PugElBCf4PFpxhErSzU3/PY5sFL5Z6rfv4AbGAck=
+github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e/go.mod h1:alcuEEnZsY1WQsagKhZDsoPCRoOijYqhZvPwLG0kzVs=
+github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4=
+github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
+github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
+github.com/klauspost/compress v1.8.2/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
+github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
+github.com/klauspost/compress v1.12.2 h1:2KCfW3I9M7nSc5wOqXAlW2v2U6v+w6cbjvbfp+OykW8=
+github.com/klauspost/compress v1.12.2/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg=
+github.com/klauspost/cpuid v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
+github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
+github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
+github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
+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.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
+github.com/leaanthony/clir v1.0.4/go.mod h1:k/RBkdkFl18xkkACMCLt09bhiZnrGORoxmomeMvDpE0=
+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/go-ansi-parser v1.0.1 h1:97v6c5kYppVsbScf4r/VZdXyQ21KQIfeQOk2DgKxGG4=
+github.com/leaanthony/go-ansi-parser v1.0.1/go.mod h1:7arTzgVI47srICYhvgUV4CGd063sGEeoSlych5yeSPM=
+github.com/leaanthony/go-common-file-dialog v1.0.3 h1:O0uGjKnWtdEADGrkg+TyAAbZylykMwwx/MNEXn9fp+Y=
+github.com/leaanthony/go-common-file-dialog v1.0.3/go.mod h1:TGhEc9eSJgRsupZ+iH1ZgAOnEo9zp05cRH2j08RPrF0=
+github.com/leaanthony/go-webview2 v0.0.0-20210928094513-a94a08b538bd h1:6m4zZ/esiByaDbzgdvDxjsOaIDgtuG1q2cyhjAi6uAg=
+github.com/leaanthony/go-webview2 v0.0.0-20210928094513-a94a08b538bd/go.mod h1:lS5ds4bruPk9d7lzdF/OH31Z0YCerI6MmHNFGsWoUnM=
+github.com/leaanthony/gosod v1.0.3/go.mod h1:BJ2J+oHsQIyIQpnLPjnqFGTMnOZXDbvWtRCSG7jGxs4=
+github.com/leaanthony/idgen v1.0.0/go.mod h1:4nBZnt8ml/f/ic/EVQuLxuj817RccT2fyrUaZFxrcVA=
+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/typescriptify-golang-structs v0.1.7 h1:yoznzWzyxkO/iWdlpq+aPcuJ5Y/hpjq/lmgMFmpjwl0=
+github.com/leaanthony/typescriptify-golang-structs v0.1.7/go.mod h1:cWtOkiVhMF77e6phAXUcfNwYmMwCJ67Sij24lfvi9Js=
+github.com/leaanthony/webview2runtime v1.1.0 h1:N0pv55ift8XtqozIp4PNOtRCJ/Qdd/qzx80lUpalS4c=
+github.com/leaanthony/webview2runtime v1.1.0/go.mod h1:hH9GnWCve3DYzNaPOcPbhHQ7fodXR1QJNsnwixid4Tk=
+github.com/leaanthony/winc v0.0.0-20210921073452-54963136bf18 h1:5iOd93PZbpH4Iir8QkC4coFD+zEQEZSIRcjwjTFZkr0=
+github.com/leaanthony/winc v0.0.0-20210921073452-54963136bf18/go.mod h1:KEbMsKoznsebyGHwLk5LqkFOxL5uXSRdvpP4+avmAMs=
+github.com/leaanthony/winicon v1.0.0/go.mod h1:en5xhijl92aphrJdmRPlh4NI1L6wq3gEm0LpXAPghjU=
+github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
+github.com/logrusorgru/aurora v0.0.0-20181002194514-a7b3b318ed4e/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4=
+github.com/matryer/is v1.4.0 h1:sosSmIWwkYITGrxZ25ULNDeKiMNzFSr4V/eqBQP0PeE=
+github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU=
+github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
+github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
+github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
+github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
+github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
+github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8=
+github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
+github.com/olekukonko/tablewriter v0.0.4/go.mod h1:zq6QwlOf5SlnkVbMSr5EoBv3636FWnp+qbPhuoO21uA=
+github.com/pkg/browser v0.0.0-20210706143420-7d21f8c997e2 h1:acNfDZXmm28D2Yg/c3ALnZStzNaZMSagpbr96vY6Zjc=
+github.com/pkg/browser v0.0.0-20210706143420-7d21f8c997e2/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI=
+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/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/savsgio/gotils v0.0.0-20200117113501-90175b0fbe3f h1:PgA+Olipyj258EIEYnpFFONrrCcAIWNUNoFhUfMqAGY=
+github.com/savsgio/gotils v0.0.0-20200117113501-90175b0fbe3f/go.mod h1:lHhJedqxCoHN+zMtwGNTXWmF0u9Jt363FYRhV6g0CdY=
+github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
+github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
+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/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
+github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
+github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
+github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
+github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/tc-hib/winres v0.1.5/go.mod h1:pe6dOR40VOrGz8PkzreVKNvEKnlE8t4yR8A8naL+t7A=
+github.com/tdewolff/minify v2.3.6+incompatible/go.mod h1:9Ov578KJUmAWpS6NeZwRZyT56Uf6o3Mcz9CEsg8USYs=
+github.com/tdewolff/parse v2.3.4+incompatible/go.mod h1:8oBwCsVmUkgHO8M5iCzSIDtpzXOT0WXX9cWhz+bIzJQ=
+github.com/tdewolff/test v1.0.6/go.mod h1:6DAvZliBAAnD7rhVgwaM7DE5/d9NMOAJ09SqYqeK4QE=
+github.com/tidwall/gjson v1.8.0/go.mod h1:5/xDoumyyDNerp2U36lyolv46b3uF/9Bu6OfyQ9GImk=
+github.com/tidwall/match v1.0.3/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
+github.com/tidwall/pretty v1.1.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
+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.5/go.mod h1:ECbqLgccecY5kPmPmXg1MrHW585yMcDkVl6IvJe64T4=
+github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
+github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
+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/fasthttp v1.9.0/go.mod h1:FstJa9V+Pj9vQ7OJie2qMHdwemEDaDiSdBnvPM1Su9w=
+github.com/valyala/fasthttp v1.26.0/go.mod h1:cmWIqlu99AO/RKcp1HWaViTqc57FswJOfYYdPJBl8BA=
+github.com/valyala/fasthttp v1.28.0 h1:ruVmTmZaBR5i67NqnjvvH5gEv0zwHfWtbjoyW98iho4=
+github.com/valyala/fasthttp v1.28.0/go.mod h1:cmWIqlu99AO/RKcp1HWaViTqc57FswJOfYYdPJBl8BA=
+github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio=
+github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8=
+github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc=
+github.com/wailsapp/wails/v2 v2.0.0-beta.3 h1:8vhBbnjpYDF6cCUwKadon7J/98UjcP1nrnptUl70Tfg=
+github.com/wailsapp/wails/v2 v2.0.0-beta.3/go.mod h1:aku28riyHF2G5jmx/qtxjLWi7VwpTjhhX/HVLCptWFA=
+github.com/wzshiming/ctc v1.2.3/go.mod h1:2tVAtIY7SUyraSk0JxvwmONNPFL4ARavPuEsg5+KA28=
+github.com/wzshiming/winseq v0.0.0-20200112104235-db357dc107ae/go.mod h1:VTAq37rkGeV+WOybvZwjXiJOicICdpLCN8ifpISjK20=
+github.com/xanzy/ssh-agent v0.3.0/go.mod h1:3s9xbODqPuuhK9JV1R321M/FlMZSBvE5aY6eAcqrDh0=
+github.com/xyproto/xpm v1.2.1/go.mod h1:cMnesLsD0PBXLgjDfTDEaKr8XyTFsnP1QycSqRw7BiY=
+github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
+github.com/ztrue/tracerr v0.3.0/go.mod h1:qEalzze4VN9O8tnhBXScfCrmoJo10o8TN5ciKjm6Mww=
+golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
+golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
+golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
+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/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
+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-20210505024714-0287a6fb4125/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
+golang.org/x/net v0.0.0-20210510120150-4163338589ed h1:p9UgmWI9wKpfYmgaV/IZKGdXc5qEK45tDwwwDyjS26I=
+golang.org/x/net v0.0.0-20210510120150-4163338589ed/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
+golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+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-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200107162124-548cf772de50/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200810151505-1b9f1253b3ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20210611083646-a4fc73990273/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6 h1:foEbQz/B0Oz6YIqu/69kfXPYeFQAuuMYFkjaqXzl5Wo=
+golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
+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/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
+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.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
+golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/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=
+google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
+google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
+gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
+gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
+gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
+gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+nhooyr.io/websocket v1.8.6/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0=
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates/vanilla/main.tmpl.go b/v2/cmd/wails/internal/commands/initialise/templates/templates/vanilla/main.tmpl.go
new file mode 100644
index 000000000..28d7826d9
--- /dev/null
+++ b/v2/cmd/wails/internal/commands/initialise/templates/templates/vanilla/main.tmpl.go
@@ -0,0 +1,54 @@
+package main
+
+import (
+ "embed"
+ "log"
+
+ "github.com/wailsapp/wails/v2"
+ "github.com/wailsapp/wails/v2/pkg/logger"
+ "github.com/wailsapp/wails/v2/pkg/options"
+ "github.com/wailsapp/wails/v2/pkg/options/windows"
+)
+
+//go:embed frontend/src
+var assets embed.FS
+
+func main() {
+ // Create an instance of the app structure
+ app := NewApp()
+
+ // Create application with options
+ err := wails.Run(&options.App{
+ Title: "{{.ProjectName}}",
+ Width: 720,
+ Height: 570,
+ MinWidth: 720,
+ MinHeight: 570,
+ MaxWidth: 1280,
+ MaxHeight: 740,
+ DisableResize: false,
+ Fullscreen: false,
+ Frameless: false,
+ StartHidden: false,
+ HideWindowOnClose: false,
+ RGBA: &options.RGBA{R: 255, G: 255, B: 255, A: 255},
+ Assets: assets,
+ LogLevel: logger.DEBUG,
+ OnStartup: app.startup,
+ OnDomReady: app.domReady,
+ OnShutdown: app.shutdown,
+ Bind: []interface{}{
+ app,
+ },
+ // Windows platform specific options
+ Windows: &windows.Options{
+ WebviewIsTransparent: false,
+ WindowIsTranslucent: false,
+ DisableWindowIcon: false,
+ },
+ })
+
+ if err != nil {
+ log.Fatal(err)
+ }
+}
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates/vanilla/template.json b/v2/cmd/wails/internal/commands/initialise/templates/templates/vanilla/template.json
new file mode 100644
index 000000000..f235e50e7
--- /dev/null
+++ b/v2/cmd/wails/internal/commands/initialise/templates/templates/vanilla/template.json
@@ -0,0 +1,7 @@
+{
+ "name": "Vanilla HTML/JS/CSS",
+ "shortname": "vanilla",
+ "author": "Lea Anthony ",
+ "description": "A simple template using only HTML/CSS/JS",
+ "helpurl": "https://github.com/wailsapp/wails"
+}
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates/vanilla/wails.tmpl.json b/v2/cmd/wails/internal/commands/initialise/templates/templates/vanilla/wails.tmpl.json
new file mode 100644
index 000000000..0f6a23103
--- /dev/null
+++ b/v2/cmd/wails/internal/commands/initialise/templates/templates/vanilla/wails.tmpl.json
@@ -0,0 +1,9 @@
+{
+ "name": "{{.ProjectName}}",
+ "outputfilename": "{{.BinaryName}}",
+ "assetdir": "frontend/src",
+ "author": {
+ "name": "{{.AuthorName}}",
+ "email": "{{.AuthorEmail}}"
+ }
+}
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates_test.go b/v2/cmd/wails/internal/commands/initialise/templates/templates_test.go
new file mode 100644
index 000000000..dcff8d6e8
--- /dev/null
+++ b/v2/cmd/wails/internal/commands/initialise/templates/templates_test.go
@@ -0,0 +1,46 @@
+package templates
+
+import (
+ "fmt"
+ "testing"
+
+ "github.com/matryer/is"
+)
+
+func TestList(t *testing.T) {
+
+ is2 := is.New(t)
+ templates, err := List()
+ is2.NoErr(err)
+
+ println("Found these templates:")
+ for _, template := range templates {
+ fmt.Printf("%+v\n", template)
+ }
+}
+
+func TestShortname(t *testing.T) {
+
+ is2 := is.New(t)
+
+ template, err := getTemplateByShortname("vanilla")
+ is2.NoErr(err)
+
+ println("Found this template:")
+ fmt.Printf("%+v\n", template)
+}
+
+func TestInstall(t *testing.T) {
+
+ is2 := is.New(t)
+
+ options := &Options{
+ ProjectName: "test",
+ TemplateName: "vanilla",
+ AuthorName: "Lea Anthony",
+ AuthorEmail: "lea.anthony@gmail.com",
+ }
+
+ _, _, err := Install(options)
+ is2.NoErr(err)
+}
diff --git a/v2/cmd/wails/internal/commands/update/update.go b/v2/cmd/wails/internal/commands/update/update.go
new file mode 100644
index 000000000..5eef6af25
--- /dev/null
+++ b/v2/cmd/wails/internal/commands/update/update.go
@@ -0,0 +1,166 @@
+package update
+
+import (
+ "fmt"
+ "io"
+ "log"
+ "os"
+
+ "github.com/wailsapp/wails/v2/internal/shell"
+
+ "github.com/wailsapp/wails/v2/internal/github"
+
+ "github.com/leaanthony/clir"
+ "github.com/wailsapp/wails/v2/pkg/clilogger"
+)
+
+// AddSubcommand adds the `init` command for the Wails application
+func AddSubcommand(app *clir.Cli, w io.Writer, currentVersion string) error {
+
+ command := app.NewSubCommand("update", "Update the Wails CLI")
+ command.LongDescription(`This command allows you to update your version of the Wails CLI.`)
+
+ // Setup flags
+ var prereleaseRequired bool
+ command.BoolFlag("pre", "Update CLI to latest Prerelease", &prereleaseRequired)
+
+ var specificVersion string
+ command.StringFlag("version", "Install a specific version (Overrides other flags) of the CLI", &specificVersion)
+
+ command.Action(func() error {
+
+ // Create logger
+ logger := clilogger.New(w)
+
+ // Print banner
+ app.PrintBanner()
+ logger.Println("Checking for updates...")
+
+ var desiredVersion *github.SemanticVersion
+ var err error
+ var valid bool
+
+ if len(specificVersion) > 0 {
+ // Check if this is a valid version
+ valid, err = github.IsValidTag(specificVersion)
+ if err == nil {
+ if !valid {
+ err = fmt.Errorf("version '%s' is invalid", specificVersion)
+ } else {
+ desiredVersion, err = github.NewSemanticVersion(specificVersion)
+ }
+ }
+ } else {
+ if prereleaseRequired {
+ desiredVersion, err = github.GetLatestPreRelease()
+ } else {
+ desiredVersion, err = github.GetLatestStableRelease()
+ }
+ }
+ if err != nil {
+ return err
+ }
+ fmt.Println()
+
+ fmt.Println(" Current Version : " + currentVersion)
+
+ if len(specificVersion) > 0 {
+ fmt.Printf(" Desired Version : v%s\n", desiredVersion)
+ } else {
+ if prereleaseRequired {
+ fmt.Printf(" Latest Prerelease : v%s\n", desiredVersion)
+ } else {
+ fmt.Printf(" Latest Release : v%s\n", desiredVersion)
+ }
+ }
+
+ return updateToVersion(logger, desiredVersion, len(specificVersion) > 0, currentVersion)
+ })
+
+ return nil
+}
+
+func updateToVersion(logger *clilogger.CLILogger, targetVersion *github.SemanticVersion, force bool, currentVersion string) error {
+
+ var targetVersionString = "v" + targetVersion.String()
+
+ // Early exit
+ if targetVersionString == currentVersion {
+ logger.Println("\nLooks like you're up to date!")
+ return nil
+ }
+
+ var desiredVersion string
+
+ if !force {
+
+ compareVersion := currentVersion
+
+ currentVersion, err := github.NewSemanticVersion(compareVersion)
+ if err != nil {
+ return err
+ }
+
+ var success bool
+
+ // Release -> Pre-Release = Massage current version to prerelease format
+ if targetVersion.IsPreRelease() && currentVersion.IsRelease() {
+ testVersion, err := github.NewSemanticVersion(compareVersion + "-0")
+ if err != nil {
+ return err
+ }
+ success, _ = targetVersion.IsGreaterThan(testVersion)
+ }
+ // Pre-Release -> Release = Massage target version to prerelease format
+ if targetVersion.IsRelease() && currentVersion.IsPreRelease() {
+ // We are ok with greater than or equal
+ mainversion := currentVersion.MainVersion()
+ targetVersion, err = github.NewSemanticVersion(targetVersion.String())
+ if err != nil {
+ return err
+ }
+ success, _ = targetVersion.IsGreaterThanOrEqual(mainversion)
+ }
+
+ // Release -> Release = Standard check
+ if (targetVersion.IsRelease() && currentVersion.IsRelease()) ||
+ (targetVersion.IsPreRelease() && currentVersion.IsPreRelease()) {
+
+ success, _ = targetVersion.IsGreaterThan(currentVersion)
+ }
+
+ // Compare
+ if !success {
+ logger.Println("Error: The requested version is lower than the current version.")
+ logger.Println("If this is what you really want to do, use `wails update -version %s`", targetVersionString)
+ return nil
+ }
+
+ desiredVersion = "v" + targetVersion.String()
+
+ } else {
+ desiredVersion = "v" + targetVersion.String()
+ }
+
+ fmt.Println()
+ logger.Print("Installing Wails CLI " + desiredVersion + "...")
+
+ // Run command in non module directory
+ homeDir, err := os.UserHomeDir()
+ if err != nil {
+ log.Fatal("Cannot find home directory! Please file a bug report!")
+ }
+
+ sout, serr, err := shell.RunCommand(homeDir, "go", "install", "github.com/wailsapp/wails/v2/cmd/wails@"+desiredVersion)
+ if err != nil {
+ logger.Println("Failed.")
+ logger.Println(sout + `\n` + serr)
+ return err
+ }
+ logger.Println("\n")
+ logger.Println("Wails CLI updated to " + desiredVersion)
+ logger.Println("Make sure you update your project go.mod file to use " + desiredVersion + ":")
+ logger.Println(" require github.com/wailsapp/wails/v2 " + desiredVersion)
+
+ return nil
+}
diff --git a/v2/cmd/wails/internal/tags.go b/v2/cmd/wails/internal/tags.go
new file mode 100644
index 000000000..42743028d
--- /dev/null
+++ b/v2/cmd/wails/internal/tags.go
@@ -0,0 +1,15 @@
+package internal
+
+import "strings"
+
+// ParseUserTags takes the string form of tags and converts to a slice of strings
+func ParseUserTags(tagString string) []string {
+ userTags := make([]string, 0)
+ for _, tag := range strings.Split(tagString, " ") {
+ thisTag := strings.TrimSpace(tag)
+ if thisTag != "" {
+ userTags = append(userTags, thisTag)
+ }
+ }
+ return userTags
+}
diff --git a/v2/cmd/wails/internal/version.go b/v2/cmd/wails/internal/version.go
new file mode 100644
index 000000000..4e6e434db
--- /dev/null
+++ b/v2/cmd/wails/internal/version.go
@@ -0,0 +1,3 @@
+package internal
+
+var Version = "v2.0.0-beta.15"
diff --git a/v2/cmd/wails/main.go b/v2/cmd/wails/main.go
new file mode 100644
index 000000000..e69db18d7
--- /dev/null
+++ b/v2/cmd/wails/main.go
@@ -0,0 +1,82 @@
+package main
+
+import (
+ "fmt"
+ "github.com/wailsapp/wails/v2/cmd/wails/internal"
+ "os"
+
+ "github.com/wailsapp/wails/v2/internal/colour"
+
+ "github.com/wailsapp/wails/v2/cmd/wails/internal/commands/update"
+
+ "github.com/leaanthony/clir"
+ "github.com/wailsapp/wails/v2/cmd/wails/internal/commands/build"
+ "github.com/wailsapp/wails/v2/cmd/wails/internal/commands/dev"
+ "github.com/wailsapp/wails/v2/cmd/wails/internal/commands/doctor"
+ "github.com/wailsapp/wails/v2/cmd/wails/internal/commands/generate"
+ "github.com/wailsapp/wails/v2/cmd/wails/internal/commands/initialise"
+)
+
+func fatal(message string) {
+ println(message)
+ os.Exit(1)
+}
+
+func banner(_ *clir.Cli) string {
+ return fmt.Sprintf("%s %s\n",
+ colour.Yellow("Wails CLI"),
+ colour.DarkRed(internal.Version))
+}
+
+func printFooter() {
+ println(colour.Yellow("\nIf Wails is useful to you or your company, please consider sponsoring the project:\nhttps://github.com/sponsors/leaanthony\n"))
+}
+
+func main() {
+
+ var err error
+
+ app := clir.NewCli("Wails", "Go/HTML Appkit", internal.Version)
+
+ app.SetBannerFunction(banner)
+ defer printFooter()
+
+ build.AddBuildSubcommand(app, os.Stdout)
+ err = initialise.AddSubcommand(app, os.Stdout)
+ if err != nil {
+ fatal(err.Error())
+ }
+
+ err = doctor.AddSubcommand(app, os.Stdout)
+ if err != nil {
+ fatal(err.Error())
+ }
+
+ err = dev.AddSubcommand(app, os.Stdout)
+ if err != nil {
+ fatal(err.Error())
+ }
+
+ err = generate.AddSubcommand(app, os.Stdout)
+ if err != nil {
+ fatal(err.Error())
+ }
+
+ err = update.AddSubcommand(app, os.Stdout, internal.Version)
+ if err != nil {
+ fatal(err.Error())
+ }
+
+ command := app.NewSubCommand("version", "The Wails CLI version")
+ command.Action(func() error {
+ println(internal.Version)
+ return nil
+ })
+
+ err = app.Run()
+ if err != nil {
+ println("\n\nERROR: " + err.Error())
+ printFooter()
+ os.Exit(1)
+ }
+}
diff --git a/v2/go.mod b/v2/go.mod
new file mode 100644
index 000000000..d0058db4b
--- /dev/null
+++ b/v2/go.mod
@@ -0,0 +1,82 @@
+module github.com/wailsapp/wails/v2
+
+go 1.17
+
+require (
+ github.com/Masterminds/semver v1.5.0
+ github.com/fatih/structtag v1.2.0
+ github.com/flytam/filenamify v1.0.0
+ github.com/fsnotify/fsnotify v1.4.9
+ github.com/gabriel-vasile/mimetype v1.3.1
+ github.com/go-git/go-billy/v5 v5.2.0 // indirect
+ github.com/go-git/go-git/v5 v5.3.0
+ github.com/gofiber/fiber/v2 v2.17.0
+ github.com/gofiber/websocket/v2 v2.0.8
+ github.com/golang/protobuf v1.5.2 // indirect
+ github.com/google/uuid v1.1.2 // indirect
+ github.com/gorilla/websocket v1.4.1
+ github.com/imdario/mergo v0.3.12
+ github.com/jackmordaunt/icns v1.0.0
+ github.com/leaanthony/clir v1.0.4
+ github.com/leaanthony/debme v1.2.1
+ github.com/leaanthony/go-ansi-parser v1.0.1
+ github.com/leaanthony/go-common-file-dialog v1.0.3
+ github.com/leaanthony/go-webview2 v0.0.0-20211022194343-1e4c8d4226f3
+ github.com/leaanthony/gosod v1.0.3
+ github.com/leaanthony/idgen v1.0.0
+ github.com/leaanthony/slicer v1.5.0
+ github.com/leaanthony/typescriptify-golang-structs v0.1.7
+ github.com/leaanthony/webview2runtime v1.1.0
+ github.com/leaanthony/winc v0.0.0-20210921073452-54963136bf18
+ github.com/leaanthony/winicon v1.0.0
+ github.com/matryer/is v1.4.0
+ github.com/olekukonko/tablewriter v0.0.4
+ github.com/pkg/browser v0.0.0-20210706143420-7d21f8c997e2
+ github.com/pkg/errors v0.9.1
+ github.com/tc-hib/winres v0.1.5
+ github.com/tdewolff/minify v2.3.6+incompatible
+ github.com/tdewolff/parse v2.3.4+incompatible // indirect
+ github.com/tdewolff/test v1.0.6 // indirect
+ github.com/tidwall/sjson v1.1.7
+ github.com/wzshiming/ctc v1.2.3
+ github.com/xyproto/xpm v1.2.1
+ github.com/ztrue/tracerr v0.3.0
+ golang.org/x/mod v0.4.1
+ golang.org/x/net v0.0.0-20210510120150-4163338589ed
+ golang.org/x/sys v0.0.0-20211020174200-9d6173849985
+ golang.org/x/tools v0.1.0
+ nhooyr.io/websocket v1.8.6
+)
+
+require (
+ github.com/Microsoft/go-winio v0.4.16 // indirect
+ github.com/andybalholm/brotli v1.0.2 // indirect
+ github.com/emirpasic/gods v1.12.0 // indirect
+ github.com/fasthttp/websocket v0.0.0-20200320073529-1554a54587ab // indirect
+ github.com/go-git/gcfg v1.5.0 // indirect
+ github.com/go-ole/go-ole v1.2.5 // indirect
+ github.com/google/go-cmp v0.5.5 // 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/klauspost/compress v1.12.2 // indirect
+ github.com/logrusorgru/aurora v0.0.0-20181002194514-a7b3b318ed4e // indirect
+ github.com/mattn/go-runewidth v0.0.7 // indirect
+ github.com/mitchellh/go-homedir v1.1.0 // indirect
+ github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // indirect
+ github.com/savsgio/gotils v0.0.0-20200117113501-90175b0fbe3f // indirect
+ github.com/sergi/go-diff v1.1.0 // indirect
+ github.com/tidwall/gjson v1.8.0 // indirect
+ github.com/tidwall/match v1.0.3 // indirect
+ github.com/tidwall/pretty v1.1.0 // indirect
+ github.com/tkrajina/go-reflector v0.5.5 // indirect
+ github.com/valyala/bytebufferpool v1.0.0 // indirect
+ github.com/valyala/fasthttp v1.28.0 // indirect
+ github.com/valyala/tcplisten v1.0.0 // indirect
+ github.com/wzshiming/winseq v0.0.0-20200112104235-db357dc107ae // indirect
+ github.com/xanzy/ssh-agent v0.3.0 // indirect
+ golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a // indirect
+ golang.org/x/image v0.0.0-20201208152932-35266b937fa6 // indirect
+ golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
+ gopkg.in/warnings.v0 v0.1.2 // indirect
+)
diff --git a/v2/go.sum b/v2/go.sum
new file mode 100644
index 000000000..592545177
--- /dev/null
+++ b/v2/go.sum
@@ -0,0 +1,297 @@
+github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww=
+github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y=
+github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA=
+github.com/Microsoft/go-winio v0.4.16 h1:FtSW/jqD+l4ba5iPBj9CODVtgfYAD8w2wS923g/cFDk=
+github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0=
+github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7 h1:uSoVVbwJiQipAclBbw+8quDsfcvFjOpI5iCf4p/cqCs=
+github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs=
+github.com/andybalholm/brotli v1.0.2 h1:JKnhI/XQ75uFBTiuzXpzFrUriDPiZjlOSzh6wXogP0E=
+github.com/andybalholm/brotli v1.0.2/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y=
+github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA=
+github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
+github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
+github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
+github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
+github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
+github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/emirpasic/gods v1.12.0 h1:QAUIPSaCu4G+POclxeqb3F+WPpdKqFGlw36+yOzGlrg=
+github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o=
+github.com/fasthttp/websocket v0.0.0-20200320073529-1554a54587ab h1:9e2joQGp642wHGFP5m86SDptAavrdGBe8/x9DGEEAaI=
+github.com/fasthttp/websocket v0.0.0-20200320073529-1554a54587ab/go.mod h1:smsv/h4PBEBaU0XDTY5UwJTpZv69fQ0FfcLJr21mA6Y=
+github.com/fatih/structtag v1.2.0 h1:/OdNE99OxoI/PqaW/SuSK9uxxT3f/tcSZgon/ssNSx4=
+github.com/fatih/structtag v1.2.0/go.mod h1:mBJUNpUnHmRKrKlQQlmCrh5PuhftFbNv8Ys4/aAZl94=
+github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
+github.com/flytam/filenamify v1.0.0 h1:ewx6BY2dj7U6h2zGPJmt33q/BjkSf/YsY/woQvnUNIs=
+github.com/flytam/filenamify v1.0.0/go.mod h1:Dzf9kVycwcsBlr2ATg6uxjqiFgKGH+5SKFuhdeP5zu8=
+github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
+github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
+github.com/gabriel-vasile/mimetype v1.3.1 h1:qevA6c2MtE1RorlScnixeG0VA1H4xrXyhyX3oWBynNQ=
+github.com/gabriel-vasile/mimetype v1.3.1/go.mod h1:fA8fi6KUiG7MgQQ+mEWotXoEOvmxRtOJlERCzSmRvr8=
+github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
+github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
+github.com/gin-gonic/gin v1.6.3 h1:ahKqKTFpO5KTPHxWZjEdPScmYaGtLo8Y4DMHoEsnp14=
+github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M=
+github.com/gliderlabs/ssh v0.2.2 h1:6zsha5zo/TWhRhwqCD3+EarCAgZ2yN28ipRnGPnwkI0=
+github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
+github.com/go-git/gcfg v1.5.0 h1:Q5ViNfGF8zFgyJWPqYwA7qGFoMTEiBmdlkcfRmpIMa4=
+github.com/go-git/gcfg v1.5.0/go.mod h1:5m20vg6GwYabIxaOonVkTdrILxQMpEShl1xiMF4ua+E=
+github.com/go-git/go-billy/v5 v5.0.0/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0=
+github.com/go-git/go-billy/v5 v5.1.0/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0=
+github.com/go-git/go-billy/v5 v5.2.0 h1:GcoouCP9J+5slw2uXAocL70z8ml4A8B/H8nEPt6CLPk=
+github.com/go-git/go-billy/v5 v5.2.0/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0=
+github.com/go-git/go-git-fixtures/v4 v4.0.2-0.20200613231340-f56387b50c12 h1:PbKy9zOy4aAKrJ5pibIRpVO2BXnK1Tlcg+caKI7Ox5M=
+github.com/go-git/go-git-fixtures/v4 v4.0.2-0.20200613231340-f56387b50c12/go.mod h1:m+ICp2rF3jDhFgEZ/8yziagdT1C+ZpZcrJjappBCDSw=
+github.com/go-git/go-git/v5 v5.3.0 h1:8WKMtJR2j8RntEXR/uvTKagfEt4GYlwQ7mntE4+0GWc=
+github.com/go-git/go-git/v5 v5.3.0/go.mod h1:xdX4bWJ48aOrdhnl2XqHYstHbbp6+LFS4r4X+lNVprw=
+github.com/go-ole/go-ole v1.2.4/go.mod h1:XCwSNxSkXRo4vlyPy93sltvi/qJq0jqQhjqQNIwKuxM=
+github.com/go-ole/go-ole v1.2.5 h1:t4MGB5xEDZvXI+0rMjjsfBsD7yAgp/s9ZDkL1JndXwY=
+github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
+github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
+github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q=
+github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
+github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no=
+github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
+github.com/go-playground/validator/v10 v10.2.0 h1:KgJ0snyC2R9VXYN2rneOtQcw5aHQB1Vv0sFl1UcHBOY=
+github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI=
+github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee h1:s+21KNqlpePfkah2I+gwHF8xmJWRjooY+5248k6m4A0=
+github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo=
+github.com/gobwas/pool v0.2.0 h1:QEmUOlnSjWtnpRGHF3SauEiOsy82Cup83Vf2LcMlnc8=
+github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw=
+github.com/gobwas/ws v1.0.2 h1:CoAavW/wd/kulfZmSIBt6p24n4j7tHgNVCjsfHVNUbo=
+github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM=
+github.com/gofiber/fiber/v2 v2.17.0 h1:qP3PkGUbBB0i9iQh5E057XI1yO5CZigUxZhyUFYAFoM=
+github.com/gofiber/fiber/v2 v2.17.0/go.mod h1:iftruuHGkRYGEXVISmdD7HTYWyfS2Bh+Dkfq4n/1Owg=
+github.com/gofiber/websocket/v2 v2.0.8 h1:Hb4y6IxYZVMO0segROODXJiXVgVD3a6i7wnfot8kM6k=
+github.com/gofiber/websocket/v2 v2.0.8/go.mod h1:fv8HSGQX09sauNv9g5Xq8GeGAaahLFYQKKb4ZdT0x2w=
+github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
+github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
+github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
+github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
+github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
+github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
+github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
+github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
+github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
+github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y=
+github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/gorilla/websocket v1.4.1 h1:q7AeDBpnBk8AogcD4DSag/Ukw/KV+YhzLj2bP5HvKCM=
+github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
+github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU=
+github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
+github.com/jackmordaunt/icns v1.0.0 h1:RYSxplerf/l/DUd09AHtITwckkv/mqjVv4DjYdPmAMQ=
+github.com/jackmordaunt/icns v1.0.0/go.mod h1:7TTQVEuGzVVfOPPlLNHJIkzA6CoV7aH1Dv9dW351oOo=
+github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=
+github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
+github.com/jchv/go-winloader v0.0.0-20200815041850-dec1ee9a7fd5/go.mod h1:alcuEEnZsY1WQsagKhZDsoPCRoOijYqhZvPwLG0kzVs=
+github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e h1:Q3+PugElBCf4PFpxhErSzU3/PY5sFL5Z6rfv4AbGAck=
+github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e/go.mod h1:alcuEEnZsY1WQsagKhZDsoPCRoOijYqhZvPwLG0kzVs=
+github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4=
+github.com/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGns=
+github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
+github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351 h1:DowS9hvgyYSX4TO5NpyC606/Z4SxnNYbT+WX27or6Ck=
+github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
+github.com/klauspost/compress v1.8.2/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
+github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
+github.com/klauspost/compress v1.12.2 h1:2KCfW3I9M7nSc5wOqXAlW2v2U6v+w6cbjvbfp+OykW8=
+github.com/klauspost/compress v1.12.2/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg=
+github.com/klauspost/cpuid v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
+github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
+github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
+github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
+github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
+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.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
+github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
+github.com/leaanthony/clir v1.0.4 h1:Dov2y9zWJmZr7CjaCe86lKa4b5CSxskGAt2yBkoDyiU=
+github.com/leaanthony/clir v1.0.4/go.mod h1:k/RBkdkFl18xkkACMCLt09bhiZnrGORoxmomeMvDpE0=
+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/go-ansi-parser v1.0.1 h1:97v6c5kYppVsbScf4r/VZdXyQ21KQIfeQOk2DgKxGG4=
+github.com/leaanthony/go-ansi-parser v1.0.1/go.mod h1:7arTzgVI47srICYhvgUV4CGd063sGEeoSlych5yeSPM=
+github.com/leaanthony/go-common-file-dialog v1.0.3 h1:O0uGjKnWtdEADGrkg+TyAAbZylykMwwx/MNEXn9fp+Y=
+github.com/leaanthony/go-common-file-dialog v1.0.3/go.mod h1:TGhEc9eSJgRsupZ+iH1ZgAOnEo9zp05cRH2j08RPrF0=
+github.com/leaanthony/go-webview2 v0.0.0-20211022194343-1e4c8d4226f3 h1:qhgrg3MhFRAIvtaqoqI+SrT+0wDYpxDMp9e3cvcxMpI=
+github.com/leaanthony/go-webview2 v0.0.0-20211022194343-1e4c8d4226f3/go.mod h1:lS5ds4bruPk9d7lzdF/OH31Z0YCerI6MmHNFGsWoUnM=
+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/idgen v1.0.0 h1:IZreR+JGEzFV4yeVuBZA25gM0keUoFy+RDUldncQ+Jw=
+github.com/leaanthony/idgen v1.0.0/go.mod h1:4nBZnt8ml/f/ic/EVQuLxuj817RccT2fyrUaZFxrcVA=
+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/typescriptify-golang-structs v0.1.7 h1:yoznzWzyxkO/iWdlpq+aPcuJ5Y/hpjq/lmgMFmpjwl0=
+github.com/leaanthony/typescriptify-golang-structs v0.1.7/go.mod h1:cWtOkiVhMF77e6phAXUcfNwYmMwCJ67Sij24lfvi9Js=
+github.com/leaanthony/webview2runtime v1.1.0 h1:N0pv55ift8XtqozIp4PNOtRCJ/Qdd/qzx80lUpalS4c=
+github.com/leaanthony/webview2runtime v1.1.0/go.mod h1:hH9GnWCve3DYzNaPOcPbhHQ7fodXR1QJNsnwixid4Tk=
+github.com/leaanthony/winc v0.0.0-20210921073452-54963136bf18 h1:5iOd93PZbpH4Iir8QkC4coFD+zEQEZSIRcjwjTFZkr0=
+github.com/leaanthony/winc v0.0.0-20210921073452-54963136bf18/go.mod h1:KEbMsKoznsebyGHwLk5LqkFOxL5uXSRdvpP4+avmAMs=
+github.com/leaanthony/winicon v1.0.0 h1:ZNt5U5dY71oEoKZ97UVwJRT4e+5xo5o/ieKuHuk8NqQ=
+github.com/leaanthony/winicon v1.0.0/go.mod h1:en5xhijl92aphrJdmRPlh4NI1L6wq3gEm0LpXAPghjU=
+github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y=
+github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
+github.com/logrusorgru/aurora v0.0.0-20181002194514-a7b3b318ed4e h1:9MlwzLdW7QSDrhDjFlsEYmxpFyIoXmYRon3dt0io31k=
+github.com/logrusorgru/aurora v0.0.0-20181002194514-a7b3b318ed4e/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4=
+github.com/matryer/is v1.4.0 h1:sosSmIWwkYITGrxZ25ULNDeKiMNzFSr4V/eqBQP0PeE=
+github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU=
+github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
+github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
+github.com/mattn/go-runewidth v0.0.7 h1:Ei8KR0497xHyKJPAv59M1dkC+rOZCMBJ+t3fZ+twI54=
+github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
+github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
+github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
+github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc=
+github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
+github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 h1:Esafd1046DLDQ0W1YjYsBW+p8U2u7vzgW2SQVmlNazg=
+github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
+github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ=
+github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8=
+github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
+github.com/olekukonko/tablewriter v0.0.4 h1:vHD/YYe1Wolo78koG299f7V/VAS08c6IpCLn+Ejf/w8=
+github.com/olekukonko/tablewriter v0.0.4/go.mod h1:zq6QwlOf5SlnkVbMSr5EoBv3636FWnp+qbPhuoO21uA=
+github.com/pkg/browser v0.0.0-20210706143420-7d21f8c997e2 h1:acNfDZXmm28D2Yg/c3ALnZStzNaZMSagpbr96vY6Zjc=
+github.com/pkg/browser v0.0.0-20210706143420-7d21f8c997e2/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI=
+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/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/savsgio/gotils v0.0.0-20200117113501-90175b0fbe3f h1:PgA+Olipyj258EIEYnpFFONrrCcAIWNUNoFhUfMqAGY=
+github.com/savsgio/gotils v0.0.0-20200117113501-90175b0fbe3f/go.mod h1:lHhJedqxCoHN+zMtwGNTXWmF0u9Jt363FYRhV6g0CdY=
+github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
+github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
+github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
+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/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
+github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
+github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
+github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
+github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+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/tdewolff/minify v2.3.6+incompatible h1:2hw5/9ZvxhWLvBUnHE06gElGYz+Jv9R4Eys0XUzItYo=
+github.com/tdewolff/minify v2.3.6+incompatible/go.mod h1:9Ov578KJUmAWpS6NeZwRZyT56Uf6o3Mcz9CEsg8USYs=
+github.com/tdewolff/parse v2.3.4+incompatible h1:x05/cnGwIMf4ceLuDMBOdQ1qGniMoxpP46ghf0Qzh38=
+github.com/tdewolff/parse v2.3.4+incompatible/go.mod h1:8oBwCsVmUkgHO8M5iCzSIDtpzXOT0WXX9cWhz+bIzJQ=
+github.com/tdewolff/test v1.0.6 h1:76mzYJQ83Op284kMT+63iCNCI7NEERsIN8dLM+RiKr4=
+github.com/tdewolff/test v1.0.6/go.mod h1:6DAvZliBAAnD7rhVgwaM7DE5/d9NMOAJ09SqYqeK4QE=
+github.com/tidwall/gjson v1.8.0 h1:Qt+orfosKn0rbNTZqHYDqBrmm3UDA4KRkv70fDzG+PQ=
+github.com/tidwall/gjson v1.8.0/go.mod h1:5/xDoumyyDNerp2U36lyolv46b3uF/9Bu6OfyQ9GImk=
+github.com/tidwall/match v1.0.3 h1:FQUVvBImDutD8wJLN6c5eMzWtjgONK9MwIBCOrUJKeE=
+github.com/tidwall/match v1.0.3/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
+github.com/tidwall/pretty v1.1.0 h1:K3hMW5epkdAVwibsQEfR/7Zj0Qgt4DxtNumTq/VloO8=
+github.com/tidwall/pretty v1.1.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
+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/tkrajina/go-reflector v0.5.5 h1:gwoQFNye30Kk7NrExj8zm3zFtrGPqOkzFMLuQZg1DtQ=
+github.com/tkrajina/go-reflector v0.5.5/go.mod h1:ECbqLgccecY5kPmPmXg1MrHW585yMcDkVl6IvJe64T4=
+github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo=
+github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
+github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs=
+github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
+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/fasthttp v1.9.0/go.mod h1:FstJa9V+Pj9vQ7OJie2qMHdwemEDaDiSdBnvPM1Su9w=
+github.com/valyala/fasthttp v1.26.0/go.mod h1:cmWIqlu99AO/RKcp1HWaViTqc57FswJOfYYdPJBl8BA=
+github.com/valyala/fasthttp v1.28.0 h1:ruVmTmZaBR5i67NqnjvvH5gEv0zwHfWtbjoyW98iho4=
+github.com/valyala/fasthttp v1.28.0/go.mod h1:cmWIqlu99AO/RKcp1HWaViTqc57FswJOfYYdPJBl8BA=
+github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio=
+github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8=
+github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc=
+github.com/wzshiming/ctc v1.2.3 h1:q+hW3IQNsjIlOFBTGZZZeIXTElFM4grF4spW/errh/c=
+github.com/wzshiming/ctc v1.2.3/go.mod h1:2tVAtIY7SUyraSk0JxvwmONNPFL4ARavPuEsg5+KA28=
+github.com/wzshiming/winseq v0.0.0-20200112104235-db357dc107ae h1:tpXvBXC3hpQBDCc9OojJZCQMVRAbT3TTdUMP8WguXkY=
+github.com/wzshiming/winseq v0.0.0-20200112104235-db357dc107ae/go.mod h1:VTAq37rkGeV+WOybvZwjXiJOicICdpLCN8ifpISjK20=
+github.com/xanzy/ssh-agent v0.3.0 h1:wUMzuKtKilRgBAD1sUb8gOwwRr2FGoBVumcjoOACClI=
+github.com/xanzy/ssh-agent v0.3.0/go.mod h1:3s9xbODqPuuhK9JV1R321M/FlMZSBvE5aY6eAcqrDh0=
+github.com/xyproto/xpm v1.2.1 h1:trdvGjjWBsOOKzBBUPT6JvaIQM3acJEEYfbxN7M96wg=
+github.com/xyproto/xpm v1.2.1/go.mod h1:cMnesLsD0PBXLgjDfTDEaKr8XyTFsnP1QycSqRw7BiY=
+github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
+github.com/ztrue/tracerr v0.3.0 h1:lDi6EgEYhPYPnKcjsYzmWw4EkFEoA/gfe+I9Y5f+h6Y=
+github.com/ztrue/tracerr v0.3.0/go.mod h1:qEalzze4VN9O8tnhBXScfCrmoJo10o8TN5ciKjm6Mww=
+golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
+golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
+golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a h1:kr2P4QFmQr29mSLA43kwrOcgcReGTfbE9N577tCTuBc=
+golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
+golang.org/x/image v0.0.0-20200430140353-33d19683fad8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
+golang.org/x/image v0.0.0-20201208152932-35266b937fa6 h1:nfeHNc1nAqecKCy2FCy4HY+soOOe5sDLJ/gZLbx6GYI=
+golang.org/x/image v0.0.0-20201208152932-35266b937fa6/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
+golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/mod v0.4.1 h1:Kvvh58BN8Y9/lBi7hTekvtMpm07eUZ0ck5pRHpsMWrY=
+golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
+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-20210505024714-0287a6fb4125/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
+golang.org/x/net v0.0.0-20210510120150-4163338589ed h1:p9UgmWI9wKpfYmgaV/IZKGdXc5qEK45tDwwwDyjS26I=
+golang.org/x/net v0.0.0-20210510120150-4163338589ed/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
+golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+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-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200107162124-548cf772de50/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200810151505-1b9f1253b3ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20210611083646-a4fc73990273/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20211020174200-9d6173849985 h1:LOlKVhfDyahgmqa97awczplwkjzNaELFg3zRIJ13RYo=
+golang.org/x/sys v0.0.0-20211020174200-9d6173849985/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E=
+golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
+golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
+golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
+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.1.0 h1:po9/4sTYwZU9lPhi1tOrb4hCv3qrhiQ77LZfGa2OjwY=
+golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
+golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/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 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
+golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
+google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk=
+google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
+gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
+gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=
+gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
+gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
+gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
+gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+nhooyr.io/websocket v1.8.6 h1:s+C3xAMLwGmlI31Nyn/eAehUlZPwfYZu2JXM621Q5/k=
+nhooyr.io/websocket v1.8.6/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0=
diff --git a/v2/init.go b/v2/init.go
new file mode 100644
index 000000000..50dc23fdb
--- /dev/null
+++ b/v2/init.go
@@ -0,0 +1,7 @@
+// +build !windows
+
+package wails
+
+func Init() error {
+ return nil
+}
diff --git a/v2/init_windows.go b/v2/init_windows.go
new file mode 100644
index 000000000..173da0a89
--- /dev/null
+++ b/v2/init_windows.go
@@ -0,0 +1,15 @@
+package wails
+
+import (
+ "fmt"
+ "syscall"
+)
+
+// Init is called at the start of the application
+func Init() error {
+ status, r, err := syscall.NewLazyDLL("user32.dll").NewProc("SetProcessDPIAware").Call()
+ if status == 0 {
+ return fmt.Errorf("exit status %d: %v %v", status, r, err)
+ }
+ return nil
+}
diff --git a/v2/internal/app/debug.go b/v2/internal/app/debug.go
new file mode 100644
index 000000000..3a6a6916f
--- /dev/null
+++ b/v2/internal/app/debug.go
@@ -0,0 +1,37 @@
+//go:build dev
+// +build dev
+
+package app
+
+import (
+ "flag"
+ "strings"
+
+ "github.com/wailsapp/wails/v2/pkg/logger"
+)
+
+// Init initialises the application for a debug environment
+func (a *App) Init() error {
+ // Indicate debug mode
+ a.debug = true
+
+ // Set log levels
+ loglevel := flag.String("loglevel", "debug", "Loglevel to use - Trace, Debug, Info, Warning, Error")
+ flag.Parse()
+ if len(*loglevel) > 0 {
+ switch strings.ToLower(*loglevel) {
+ case "trace":
+ a.logger.SetLogLevel(logger.TRACE)
+ case "info":
+ a.logger.SetLogLevel(logger.INFO)
+ case "warning":
+ a.logger.SetLogLevel(logger.WARNING)
+ case "error":
+ a.logger.SetLogLevel(logger.ERROR)
+ default:
+ a.logger.SetLogLevel(logger.DEBUG)
+ }
+ }
+
+ return nil
+}
diff --git a/v2/internal/app/default.go b/v2/internal/app/default.go
new file mode 100644
index 000000000..380c251be
--- /dev/null
+++ b/v2/internal/app/default.go
@@ -0,0 +1,41 @@
+// +build !desktop,!hybrid,!server,!dev
+
+package app
+
+// This is the default application that will get run if the user compiles using `go build`.
+// The reason we want to prevent that is that the `wails build` command does a lot of behind
+// the scenes work such as asset compilation. If we allow `go build`, the state of these assets
+// will be unknown and the application will not work as expected.
+
+import (
+ "os"
+
+ "github.com/wailsapp/wails/v2/internal/logger"
+
+ "github.com/wailsapp/wails/v2/pkg/options"
+)
+
+// App defines a Wails application structure
+type App struct {
+ Title string
+ Width int
+ Height int
+ Resizable bool
+
+ // Indicates if the app is running in debug mode
+ debug bool
+
+ logger *logger.Logger
+}
+
+// CreateApp returns a null application
+func CreateApp(_ *options.App) (*App, error) {
+ return &App{}, nil
+}
+
+// Run the application
+func (a *App) Run() error {
+ println(`FATAL: This application was built using "go build". This is unsupported. Please compile using "wails build".`)
+ os.Exit(1)
+ return nil
+}
diff --git a/v2/internal/app/desktop.go b/v2/internal/app/desktop.go
new file mode 100644
index 000000000..b27f92919
--- /dev/null
+++ b/v2/internal/app/desktop.go
@@ -0,0 +1,256 @@
+//go:build desktop && !server
+// +build desktop,!server
+
+package app
+
+import (
+ "context"
+ "sync"
+
+ "github.com/wailsapp/wails/v2/internal/binding"
+ "github.com/wailsapp/wails/v2/internal/ffenestri"
+ "github.com/wailsapp/wails/v2/internal/logger"
+ "github.com/wailsapp/wails/v2/internal/menumanager"
+ "github.com/wailsapp/wails/v2/internal/messagedispatcher"
+ "github.com/wailsapp/wails/v2/internal/servicebus"
+ "github.com/wailsapp/wails/v2/internal/signal"
+ "github.com/wailsapp/wails/v2/internal/subsystem"
+ "github.com/wailsapp/wails/v2/pkg/options"
+)
+
+// App defines a Wails application structure
+type App struct {
+ appType string
+
+ window *ffenestri.Application
+ servicebus *servicebus.ServiceBus
+ logger *logger.Logger
+ signal *signal.Manager
+ options *options.App
+
+ // Subsystems
+ log *subsystem.Log
+ runtime *subsystem.Runtime
+ event *subsystem.Event
+ //binding *subsystem.Binding
+ call *subsystem.Call
+ menu *subsystem.Menu
+ url *subsystem.URL
+ dispatcher *messagedispatcher.Dispatcher
+
+ menuManager *menumanager.Manager
+
+ // Indicates if the app is in debug mode
+ debug bool
+
+ // This is our binding DB
+ bindings *binding.Bindings
+
+ // OnStartup/OnShutdown
+ startupCallback func(ctx context.Context)
+ shutdownCallback func()
+}
+
+// Create App
+func CreateApp(appoptions *options.App) (*App, error) {
+
+ // Merge default options
+ options.MergeDefaults(appoptions)
+
+ // Set up logger
+ myLogger := logger.New(appoptions.Logger)
+ myLogger.SetLogLevel(appoptions.LogLevel)
+
+ // Create the menu manager
+ menuManager := menumanager.NewManager()
+
+ // Process the application menu
+ appMenu := options.GetApplicationMenu(appoptions)
+ menuManager.SetApplicationMenu(appMenu)
+
+ // Process context menus
+ contextMenus := options.GetContextMenus(appoptions)
+ for _, contextMenu := range contextMenus {
+ menuManager.AddContextMenu(contextMenu)
+ }
+
+ // Process tray menus
+ trayMenus := options.GetTrayMenus(appoptions)
+ for _, trayMenu := range trayMenus {
+ menuManager.AddTrayMenu(trayMenu)
+ }
+
+ window := ffenestri.NewApplicationWithConfig(appoptions, myLogger, menuManager)
+
+ // Create binding exemptions - Ugly hack. There must be a better way
+ bindingExemptions := []interface{}{appoptions.OnStartup, appoptions.OnShutdown, appoptions.OnDomReady}
+
+ result := &App{
+ appType: "desktop",
+ window: window,
+ servicebus: servicebus.New(myLogger),
+ logger: myLogger,
+ bindings: binding.NewBindings(myLogger, appoptions.Bind, bindingExemptions),
+ menuManager: menuManager,
+ startupCallback: appoptions.OnStartup,
+ shutdownCallback: appoptions.OnShutdown,
+ }
+
+ result.options = appoptions
+
+ // Initialise the app
+ err := result.Init()
+ if err != nil {
+ return nil, err
+ }
+
+ // Preflight Checks
+ err = result.PreflightChecks(appoptions)
+ if err != nil {
+ return nil, err
+ }
+
+ return result, nil
+
+}
+
+// Run the application
+func (a *App) Run() error {
+
+ var err error
+
+ // Setup a context
+ var subsystemWaitGroup sync.WaitGroup
+ parentContext := context.WithValue(context.Background(), "waitgroup", &subsystemWaitGroup)
+ ctx, cancel := context.WithCancel(parentContext)
+
+ // Start the service bus
+ a.servicebus.Debug()
+ err = a.servicebus.Start()
+ if err != nil {
+ return err
+ }
+
+ runtimesubsystem, err := subsystem.NewRuntime(ctx, a.servicebus, a.logger, a.startupCallback)
+ if err != nil {
+ return err
+ }
+ a.runtime = runtimesubsystem
+ err = a.runtime.Start()
+ if err != nil {
+ return err
+ }
+
+ // Start the logging subsystem
+ log, err := subsystem.NewLog(a.servicebus, a.logger)
+ if err != nil {
+ return err
+ }
+ a.log = log
+ err = a.log.Start()
+ if err != nil {
+ return err
+ }
+
+ // create the dispatcher
+ dispatcher, err := messagedispatcher.New(a.servicebus, a.logger)
+ if err != nil {
+ return err
+ }
+ a.dispatcher = dispatcher
+ err = dispatcher.Start()
+ if err != nil {
+ return err
+ }
+
+ if a.options.Mac.URLHandlers != nil {
+ // Start the url handler subsystem
+ url, err := subsystem.NewURL(a.servicebus, a.logger, a.options.Mac.URLHandlers)
+ if err != nil {
+ return err
+ }
+ a.url = url
+ err = a.url.Start()
+ if err != nil {
+ return err
+ }
+ }
+
+ // Start the eventing subsystem
+ eventsubsystem, err := subsystem.NewEvent(ctx, a.servicebus, a.logger)
+ if err != nil {
+ return err
+ }
+ a.event = eventsubsystem
+ err = a.event.Start()
+ if err != nil {
+ return err
+ }
+
+ // Start the menu subsystem
+ menusubsystem, err := subsystem.NewMenu(ctx, a.servicebus, a.logger, a.menuManager)
+ if err != nil {
+ return err
+ }
+ a.menu = menusubsystem
+ err = a.menu.Start()
+ if err != nil {
+ return err
+ }
+
+ // Start the call subsystem
+ callSubsystem, err := subsystem.NewCall(ctx, a.servicebus, a.logger, a.bindings.DB())
+ if err != nil {
+ return err
+ }
+ a.call = callSubsystem
+ err = a.call.Start()
+ if err != nil {
+ return err
+ }
+
+ // Dump bindings as a debug
+ bindingDump, err := a.bindings.ToJSON()
+ if err != nil {
+ return err
+ }
+
+ // Setup signal handler
+ signalsubsystem, err := signal.NewManager(ctx, cancel, a.servicebus, a.logger)
+ if err != nil {
+ return err
+ }
+ a.signal = signalsubsystem
+ a.signal.Start()
+
+ err = a.window.Run(dispatcher, bindingDump, a.debug)
+ a.logger.Trace("Ffenestri.Run() exited")
+ if err != nil {
+ return err
+ }
+
+ // Close down all the subsystems
+ a.logger.Trace("Cancelling subsystems")
+ cancel()
+ subsystemWaitGroup.Wait()
+
+ a.logger.Trace("Cancelling dispatcher")
+ dispatcher.Close()
+
+ // Close log
+ a.logger.Trace("Stopping log")
+ log.Close()
+
+ a.logger.Trace("Stopping Service bus")
+ err = a.servicebus.Stop()
+ if err != nil {
+ return err
+ }
+
+ // OnShutdown callback
+ if a.shutdownCallback != nil {
+ a.shutdownCallback()
+ }
+
+ return nil
+}
diff --git a/v2/internal/app/dev.go b/v2/internal/app/dev.go
new file mode 100644
index 000000000..3b7be059f
--- /dev/null
+++ b/v2/internal/app/dev.go
@@ -0,0 +1,249 @@
+//go:build dev
+// +build dev
+
+package app
+
+/*
+import (
+ "context"
+ "sync"
+
+ "github.com/wailsapp/wails/runtime"
+
+ "github.com/wailsapp/wails/v2/internal/bridge"
+ "github.com/wailsapp/wails/v2/internal/menumanager"
+
+ "github.com/wailsapp/wails/v2/pkg/options"
+
+ "github.com/wailsapp/wails/v2/internal/binding"
+ "github.com/wailsapp/wails/v2/internal/logger"
+ "github.com/wailsapp/wails/v2/internal/messagedispatcher"
+ "github.com/wailsapp/wails/v2/internal/servicebus"
+ "github.com/wailsapp/wails/v2/internal/signal"
+ "github.com/wailsapp/wails/v2/internal/subsystem"
+)
+
+// App defines a Wails application structure
+type App struct {
+ appType string
+
+ servicebus *servicebus.ServiceBus
+ logger *logger.Logger
+ signal *signal.Manager
+ options *options.App
+
+ // Subsystems
+ log *subsystem.Log
+ runtime *subsystem.Runtime
+ event *subsystem.Event
+ //binding *subsystem.Binding
+ call *subsystem.Call
+ menu *subsystem.Menu
+ dispatcher *messagedispatcher.Dispatcher
+
+ menuManager *menumanager.Manager
+
+ // Indicates if the app is in debug mode
+ debug bool
+
+ // This is our binding DB
+ bindings *binding.Bindings
+
+ // Application Stores
+ loglevelStore *runtime.Store
+ appconfigStore *runtime.Store
+
+ // OnStartup/OnShutdown
+ startupCallback func(*runtime.Runtime)
+ shutdownCallback func()
+
+ // Bridge
+ bridge *bridge.Bridge
+}
+
+// Create App
+func CreateApp(appoptions *options.App) (*App, error) {
+
+ // Merge default options
+ options.MergeDefaults(appoptions)
+
+ // Set up logger
+ myLogger := logger.New(appoptions.Logger)
+
+ // Create the menu manager
+ menuManager := menumanager.NewManager()
+
+ // Process the application menu
+ menuManager.SetApplicationMenu(options.GetApplicationMenu(appoptions))
+
+ // Process context menus
+ contextMenus := options.GetContextMenus(appoptions)
+ for _, contextMenu := range contextMenus {
+ menuManager.AddContextMenu(contextMenu)
+ }
+
+ // Process tray menus
+ trayMenus := options.GetTrayMenus(appoptions)
+ for _, trayMenu := range trayMenus {
+ menuManager.AddTrayMenu(trayMenu)
+ }
+
+ // Create binding exemptions - Ugly hack. There must be a better way
+ bindingExemptions := []interface{}{appoptions.OnStartup, appoptions.OnShutdown, appoptions.OnDomReady}
+
+ result := &App{
+ appType: "dev",
+ bindings: binding.NewBindings(myLogger, appoptions.Bind, bindingExemptions),
+ logger: myLogger,
+ servicebus: servicebus.New(myLogger),
+ startupCallback: appoptions.OnStartup,
+ shutdownCallback: appoptions.OnShutdown,
+ bridge: bridge.NewBridge(myLogger),
+ menuManager: menuManager,
+ }
+
+ result.options = appoptions
+
+ // Initialise the app
+ err := result.Init()
+
+ return result, err
+
+}
+
+// Run the application
+func (a *App) Run() error {
+
+ var err error
+
+ // Setup a context
+ var subsystemWaitGroup sync.WaitGroup
+ parentContext := context.WithValue(context.Background(), "waitgroup", &subsystemWaitGroup)
+ ctx, cancel := context.WithCancel(parentContext)
+ defer cancel()
+
+ // Start the service bus
+ a.servicebus.Debug()
+ err = a.servicebus.Start()
+ if err != nil {
+ return err
+ }
+
+ runtimesubsystem, err := subsystem.NewRuntime(ctx, a.servicebus, a.logger, a.startupCallback)
+ if err != nil {
+ return err
+ }
+ a.runtime = runtimesubsystem
+ err = a.runtime.Start()
+ if err != nil {
+ return err
+ }
+
+ // Application Stores
+ a.loglevelStore = a.runtime.GoRuntime().Store.New("wails:loglevel", a.options.LogLevel)
+ a.appconfigStore = a.runtime.GoRuntime().Store.New("wails:appconfig", a.options)
+
+ // Start the logging subsystem
+ log, err := subsystem.NewLog(a.servicebus, a.logger, a.loglevelStore)
+ if err != nil {
+ return err
+ }
+ a.log = log
+ err = a.log.Start()
+ if err != nil {
+ return err
+ }
+
+ // create the dispatcher
+ dispatcher, err := messagedispatcher.New(a.servicebus, a.logger)
+ if err != nil {
+ return err
+ }
+ a.dispatcher = dispatcher
+ err = dispatcher.Start()
+ if err != nil {
+ return err
+ }
+
+ // Start the eventing subsystem
+ eventsubsystem, err := subsystem.NewEvent(ctx, a.servicebus, a.logger)
+ if err != nil {
+ return err
+ }
+ a.event = eventsubsystem
+ err = a.event.Start()
+ if err != nil {
+ return err
+ }
+
+ // Start the menu subsystem
+ menusubsystem, err := subsystem.NewMenu(ctx, a.servicebus, a.logger, a.menuManager)
+ if err != nil {
+ return err
+ }
+ a.menu = menusubsystem
+ err = a.menu.Start()
+ if err != nil {
+ return err
+ }
+
+ // Start the call subsystem
+ callSubsystem, err := subsystem.NewCall(ctx, a.servicebus, a.logger, a.bindings.DB())
+ if err != nil {
+ return err
+ }
+ a.call = callSubsystem
+ err = a.call.Start()
+ if err != nil {
+ return err
+ }
+
+ // Dump bindings as a debug
+ bindingDump, err := a.bindings.ToJSON()
+ if err != nil {
+ return err
+ }
+
+ // Generate backend.js
+ a.bindings.GenerateBackendJS()
+
+ // Setup signal handler
+ signalsubsystem, err := signal.NewManager(ctx, cancel, a.servicebus, a.logger)
+ if err != nil {
+ return err
+ }
+ a.signal = signalsubsystem
+ a.signal.Start()
+
+ err = a.bridge.Run(dispatcher, a.menuManager, bindingDump, a.debug)
+ a.logger.Trace("Bridge.Run() exited")
+ if err != nil {
+ return err
+ }
+
+ // Close down all the subsystems
+ a.logger.Trace("Cancelling subsystems")
+ cancel()
+ subsystemWaitGroup.Wait()
+
+ a.logger.Trace("Cancelling dispatcher")
+ dispatcher.Close()
+
+ // Close log
+ a.logger.Trace("Stopping log")
+ log.Close()
+
+ a.logger.Trace("Stopping Service bus")
+ err = a.servicebus.Stop()
+ if err != nil {
+ return err
+ }
+
+ // OnShutdown callback
+ if a.shutdownCallback != nil {
+ a.shutdownCallback()
+ }
+ return nil
+
+}
+*/
diff --git a/v2/internal/app/hybrid.go b/v2/internal/app/hybrid.go
new file mode 100644
index 000000000..8c95c2879
--- /dev/null
+++ b/v2/internal/app/hybrid.go
@@ -0,0 +1,194 @@
+// +build !server,!desktop,hybrid
+
+package app
+
+import (
+ "os"
+ "path/filepath"
+
+ "github.com/leaanthony/clir"
+ "github.com/wailsapp/wails/v2/internal/binding"
+ "github.com/wailsapp/wails/v2/internal/ffenestri"
+ "github.com/wailsapp/wails/v2/internal/logger"
+ "github.com/wailsapp/wails/v2/internal/messagedispatcher"
+ "github.com/wailsapp/wails/v2/internal/servicebus"
+ "github.com/wailsapp/wails/v2/internal/subsystem"
+ "github.com/wailsapp/wails/v2/internal/webserver"
+)
+
+// Config defines the Application's configuration
+type Config struct {
+ Title string // Title is the value to be displayed in the title bar
+ Width int // Width is the desired window width
+ Height int // Height is the desired window height
+ DevTools bool // DevTools enables or disables the browser development tools
+ Resizable bool // Resizable when False prevents window resizing
+ ServerEnabled bool // ServerEnabled when True allows remote connections
+}
+
+// App defines a Wails application structure
+type App struct {
+ config Config
+ window *ffenestri.Application
+ webserver *webserver.WebServer
+ binding *subsystem.Binding
+ call *subsystem.Call
+ event *subsystem.Event
+ log *subsystem.Log
+ runtime *subsystem.Runtime
+
+ bindings *binding.Bindings
+ logger *logger.Logger
+ dispatcher *messagedispatcher.Dispatcher
+ servicebus *servicebus.ServiceBus
+
+ debug bool
+}
+
+// Create App
+func CreateApp(options *Options) *App {
+
+ // Merge default options
+ options.mergeDefaults()
+
+ // Set up logger
+ myLogger := logger.New(os.Stdout)
+ myLogger.SetLogLevel(logger.INFO)
+
+ window := ffenestri.NewApplicationWithConfig(&ffenestri.Config{
+ Title: options.Title,
+ Width: options.Width,
+ Height: options.Height,
+ MinWidth: options.MinWidth,
+ MinHeight: options.MinHeight,
+ MaxWidth: options.MaxWidth,
+ MaxHeight: options.MaxHeight,
+ StartHidden: options.StartHidden,
+ DevTools: options.DevTools,
+
+ Resizable: !options.DisableResize,
+ Fullscreen: options.Fullscreen,
+ }, myLogger)
+
+ app := &App{
+ window: window,
+ webserver: webserver.NewWebServer(myLogger),
+ servicebus: servicebus.New(myLogger),
+ logger: myLogger,
+ bindings: binding.NewBindings(myLogger, options.Bind),
+ }
+
+ // Initialise the app
+ app.Init()
+
+ return app
+}
+
+// Run the application
+func (a *App) Run() error {
+
+ // Default app options
+ var port = 8080
+ var ip = "localhost"
+ var suppressLogging = false
+
+ // Create CLI
+ cli := clir.NewCli(filepath.Base(os.Args[0]), "Desktop/Server Build", "")
+
+ // Setup flags
+ cli.IntFlag("p", "Port to serve on", &port)
+ cli.StringFlag("i", "IP to serve on", &ip)
+ cli.BoolFlag("q", "Suppress logging", &suppressLogging)
+
+ // Setup main action
+ cli.Action(func() error {
+
+ // Set IP + Port
+ a.webserver.SetPort(port)
+ a.webserver.SetIP(ip)
+ a.webserver.SetBindings(a.bindings)
+ // Log information (if we aren't suppressing it)
+ if !suppressLogging {
+ cli.PrintBanner()
+ a.logger.Info("Running server at %s", a.webserver.URL())
+ }
+
+ a.servicebus.Start()
+ log, err := subsystem.NewLog(a.servicebus, a.logger)
+ if err != nil {
+ return err
+ }
+ a.log = log
+ a.log.Start()
+ dispatcher, err := messagedispatcher.New(a.servicebus, a.logger)
+ if err != nil {
+ return err
+ }
+ a.dispatcher = dispatcher
+ a.dispatcher.Start()
+
+ // Start the runtime
+ runtime, err := subsystem.NewRuntime(a.servicebus, a.logger)
+ if err != nil {
+ return err
+ }
+ a.runtime = runtime
+ a.runtime.Start()
+
+ // Start the binding subsystem
+ binding, err := subsystem.NewBinding(a.servicebus, a.logger, a.bindings, runtime.GoRuntime())
+ if err != nil {
+ return err
+ }
+ a.binding = binding
+ a.binding.Start()
+
+ // Start the eventing subsystem
+ event, err := subsystem.NewEvent(a.servicebus, a.logger)
+ if err != nil {
+ return err
+ }
+ a.event = event
+ a.event.Start()
+
+ // Start the call subsystem
+ call, err := subsystem.NewCall(a.servicebus, a.logger, a.bindings.DB())
+ if err != nil {
+ return err
+ }
+ a.call = call
+ a.call.Start()
+
+ // Required so that the WailsInit functions are fired!
+ runtime.GoRuntime().Events.Emit("wails:loaded")
+
+ // Set IP + Port
+ a.webserver.SetPort(port)
+ a.webserver.SetIP(ip)
+
+ // Log information (if we aren't suppressing it)
+ if !suppressLogging {
+ cli.PrintBanner()
+ println("Running server at " + a.webserver.URL())
+ }
+
+ // Dump bindings as a debug
+ bindingDump, err := a.bindings.ToJSON()
+ if err != nil {
+ return err
+ }
+
+ go func() {
+ if err := a.webserver.Start(dispatcher, event); err != nil {
+ a.logger.Error("Webserver failed to start %s", err)
+ }
+ }()
+
+ result := a.window.Run(dispatcher, bindingDump)
+ a.servicebus.Stop()
+
+ return result
+ })
+
+ return cli.Run()
+}
diff --git a/v2/internal/app/preflight_default.go b/v2/internal/app/preflight_default.go
new file mode 100644
index 000000000..5508a7748
--- /dev/null
+++ b/v2/internal/app/preflight_default.go
@@ -0,0 +1,9 @@
+//+build !windows
+
+package app
+
+import "github.com/wailsapp/wails/v2/pkg/options"
+
+func (a *App) PreflightChecks(options *options.App) error {
+ return nil
+}
diff --git a/v2/internal/app/preflight_windows.go b/v2/internal/app/preflight_windows.go
new file mode 100644
index 000000000..29bbb7a74
--- /dev/null
+++ b/v2/internal/app/preflight_windows.go
@@ -0,0 +1,26 @@
+//+build windows
+
+package app
+
+import (
+ "github.com/wailsapp/wails/v2/internal/ffenestri/windows/wv2runtime"
+ "github.com/wailsapp/wails/v2/pkg/options"
+)
+
+func (a *App) PreflightChecks(options *options.App) error {
+
+ _ = options
+
+ // Process the webview2 runtime situation. We can pass a strategy in via the `webview2` flag for `wails build`.
+ // This will determine how wv2runtime.Process will handle a lack of valid runtime.
+ installedVersion, err := wv2runtime.Process()
+ if installedVersion != nil {
+ a.logger.Debug("WebView2 Runtime installed: Name: '%s' Version:'%s' Location:'%s'. Minimum version required: %s.",
+ installedVersion.Name, installedVersion.Version, installedVersion.Location, wv2runtime.MinimumRuntimeVersion)
+ }
+ if err != nil {
+ return err
+ }
+
+ return nil
+}
diff --git a/v2/internal/app/production.go b/v2/internal/app/production.go
new file mode 100644
index 000000000..9a2554826
--- /dev/null
+++ b/v2/internal/app/production.go
@@ -0,0 +1,12 @@
+//go:build production
+// +build production
+
+package app
+
+import "github.com/wailsapp/wails/v2/pkg/logger"
+
+// Init initialises the application for a production environment
+func (a *App) Init() error {
+ a.logger.SetLogLevel(logger.ERROR)
+ return nil
+}
diff --git a/v2/internal/app/server.go b/v2/internal/app/server.go
new file mode 100644
index 000000000..06734f0ad
--- /dev/null
+++ b/v2/internal/app/server.go
@@ -0,0 +1,165 @@
+//go:build server && !desktop
+// +build server,!desktop
+
+package app
+
+import (
+ "context"
+ "os"
+ "path/filepath"
+
+ "github.com/wailsapp/wails/v2/pkg/options"
+
+ "github.com/leaanthony/clir"
+ "github.com/wailsapp/wails/v2/internal/binding"
+ "github.com/wailsapp/wails/v2/internal/logger"
+ "github.com/wailsapp/wails/v2/internal/messagedispatcher"
+ "github.com/wailsapp/wails/v2/internal/servicebus"
+ "github.com/wailsapp/wails/v2/internal/subsystem"
+ "github.com/wailsapp/wails/v2/internal/webserver"
+)
+
+// App defines a Wails application structure
+type App struct {
+ appType string
+
+ binding *subsystem.Binding
+ call *subsystem.Call
+ event *subsystem.Event
+ log *subsystem.Log
+
+ options *options.App
+
+ bindings *binding.Bindings
+ logger *logger.Logger
+ dispatcher *messagedispatcher.Dispatcher
+ servicebus *servicebus.ServiceBus
+ webserver *webserver.WebServer
+
+ debug bool
+
+ // OnStartup/OnShutdown
+ startupCallback func(ctx context.Context)
+ shutdownCallback func()
+}
+
+// Create App
+func CreateApp(appoptions *options.App) (*App, error) {
+
+ // Merge default options
+ options.MergeDefaults(appoptions)
+
+ // Set up logger
+ myLogger := logger.New(appoptions.Logger)
+ myLogger.SetLogLevel(appoptions.LogLevel)
+
+ result := &App{
+ appType: "server",
+ bindings: binding.NewBindings(myLogger, options.Bind),
+ logger: myLogger,
+ servicebus: servicebus.New(myLogger),
+ webserver: webserver.NewWebServer(myLogger),
+ startupCallback: appoptions.OnStartup,
+ shutdownCallback: appoptions.OnShutdown,
+ }
+
+ // Initialise app
+ result.Init()
+
+ return result, nil
+}
+
+// Run the application
+func (a *App) Run() error {
+
+ // Default app options
+ var port = 8080
+ var ip = "localhost"
+ var SuppressLogging = false
+ var debugMode = false
+
+ // Create CLI
+ cli := clir.NewCli(filepath.Base(os.Args[0]), "Server Build", "")
+
+ // Setup flags
+ cli.IntFlag("p", "Port to serve on", &port)
+ cli.StringFlag("i", "IP to serve on", &ip)
+ cli.BoolFlag("d", "Debug mode", &debugMode)
+ cli.BoolFlag("q", "Suppress logging", &SuppressLogging)
+
+ // Setup main action
+ cli.Action(func() error {
+
+ // Set IP + Port
+ a.webserver.SetPort(port)
+ a.webserver.SetIP(ip)
+ a.webserver.SetBindings(a.bindings)
+ // Log information (if we aren't Suppressing it)
+ if !SuppressLogging {
+ cli.PrintBanner()
+ a.logger.Info("Running server at %s", a.webserver.URL())
+ }
+
+ if debugMode {
+ a.servicebus.Debug()
+ }
+
+ // Start the runtime
+ runtime, err := subsystem.NewRuntime(a.servicebus, a.logger, a.startupCallback)
+ if err != nil {
+ return err
+ }
+ a.runtime = runtime
+ a.runtime.Start()
+
+ a.servicebus.Start()
+ log, err := subsystem.NewLog(a.servicebus, a.logger)
+ if err != nil {
+ return err
+ }
+ a.log = log
+ a.log.Start()
+ dispatcher, err := messagedispatcher.New(a.servicebus, a.logger)
+ if err != nil {
+ return err
+ }
+ a.dispatcher = dispatcher
+ a.dispatcher.Start()
+
+ // Start the binding subsystem
+ binding, err := subsystem.NewBinding(a.servicebus, a.logger, a.bindings)
+ if err != nil {
+ return err
+ }
+ a.binding = binding
+ a.binding.Start()
+
+ // Start the eventing subsystem
+ event, err := subsystem.NewEvent(a.servicebus, a.logger)
+ if err != nil {
+ return err
+ }
+ a.event = event
+ a.event.Start()
+
+ // Start the call subsystem
+ call, err := subsystem.NewCall(a.servicebus, a.logger, a.bindings.DB(), a.runtime.GoRuntime())
+ if err != nil {
+ return err
+ }
+ a.call = call
+ a.call.Start()
+
+ // Required so that the WailsInit functions are fired!
+ runtime.GoRuntime().Events.Emit("wails:loaded")
+
+ if err := a.webserver.Start(dispatcher, event); err != nil {
+ a.logger.Error("Webserver failed to start %s", err)
+ return err
+ }
+
+ return nil
+ })
+
+ return cli.Run()
+}
diff --git a/v2/internal/appng/app_bindings.go b/v2/internal/appng/app_bindings.go
new file mode 100644
index 000000000..e314802c9
--- /dev/null
+++ b/v2/internal/appng/app_bindings.go
@@ -0,0 +1,105 @@
+//go:build bindings
+// +build bindings
+
+package appng
+
+import (
+ "github.com/leaanthony/gosod"
+ "github.com/wailsapp/wails/v2/internal/binding"
+ wailsRuntime "github.com/wailsapp/wails/v2/internal/frontend/runtime"
+ "github.com/wailsapp/wails/v2/internal/frontend/runtime/wrapper"
+ "github.com/wailsapp/wails/v2/internal/fs"
+ "github.com/wailsapp/wails/v2/internal/logger"
+ "github.com/wailsapp/wails/v2/internal/project"
+ "github.com/wailsapp/wails/v2/pkg/options"
+ "os"
+ "path/filepath"
+)
+
+// App defines a Wails application structure
+type App struct {
+ logger *logger.Logger
+ appoptions *options.App
+}
+
+func (a *App) Run() error {
+
+ // Create binding exemptions - Ugly hack. There must be a better way
+ bindingExemptions := []interface{}{a.appoptions.OnStartup, a.appoptions.OnShutdown, a.appoptions.OnDomReady}
+ appBindings := binding.NewBindings(a.logger, a.appoptions.Bind, bindingExemptions)
+
+ err := generateBindings(appBindings)
+ if err != nil {
+ return err
+ }
+ return nil
+}
+
+// CreateApp creates the app!
+func CreateApp(appoptions *options.App) (*App, error) {
+ // Set up logger
+ myLogger := logger.New(appoptions.Logger)
+ myLogger.SetLogLevel(appoptions.LogLevel)
+
+ result := &App{
+ logger: myLogger,
+ appoptions: appoptions,
+ }
+
+ return result, nil
+
+}
+
+func generateBindings(bindings *binding.Bindings) error {
+
+ cwd, err := os.Getwd()
+ if err != nil {
+ return err
+ }
+ projectConfig, err := project.Load(cwd)
+ if err != nil {
+ return err
+ }
+
+ wrapperDir := filepath.Join(projectConfig.WailsJSDir, "wailsjs", "runtime")
+ _ = os.RemoveAll(wrapperDir)
+ extractor := gosod.New(wrapper.RuntimeWrapper)
+ err = extractor.Extract(wrapperDir, nil)
+ if err != nil {
+ return err
+ }
+
+ //ipcdev.js
+ err = os.WriteFile(filepath.Join(wrapperDir, "ipcdev.js"), wailsRuntime.DesktopIPC, 0755)
+ if err != nil {
+ return err
+ }
+ //runtimedev.js
+ err = os.WriteFile(filepath.Join(wrapperDir, "runtimedev.js"), wailsRuntime.RuntimeDesktopJS, 0755)
+ if err != nil {
+ return err
+ }
+
+ targetDir := filepath.Join(projectConfig.WailsJSDir, "wailsjs", "go")
+ err = os.RemoveAll(targetDir)
+ if err != nil {
+ return err
+ }
+ _ = fs.MkDirs(targetDir)
+
+ modelsFile := filepath.Join(targetDir, "models.ts")
+ err = bindings.WriteTS(modelsFile)
+ if err != nil {
+ return err
+ }
+
+ // Write backend method wrappers
+ bindingsFilename := filepath.Join(targetDir, "bindings.js")
+ err = bindings.GenerateBackendJS(bindingsFilename, true)
+ if err != nil {
+ return err
+ }
+
+ return nil
+
+}
diff --git a/v2/internal/appng/app_darwin.go b/v2/internal/appng/app_darwin.go
new file mode 100644
index 000000000..b6f5a16a4
--- /dev/null
+++ b/v2/internal/appng/app_darwin.go
@@ -0,0 +1,15 @@
+//go:build darwin && !bindings
+
+package appng
+
+import (
+ "github.com/wailsapp/wails/v2/internal/logger"
+ "github.com/wailsapp/wails/v2/pkg/options"
+)
+
+func PreflightChecks(options *options.App, logger *logger.Logger) error {
+
+ _ = options
+
+ return nil
+}
diff --git a/v2/internal/appng/app_default_darwin.go b/v2/internal/appng/app_default_darwin.go
new file mode 100644
index 000000000..f0971f864
--- /dev/null
+++ b/v2/internal/appng/app_default_darwin.go
@@ -0,0 +1,32 @@
+//go:build !dev && !production && !bindings && darwin
+
+package appng
+
+import (
+ "fmt"
+
+ "github.com/wailsapp/wails/v2/pkg/options"
+)
+
+// App defines a Wails application structure
+type App struct{}
+
+func (a *App) Run() error {
+ return nil
+}
+
+// CreateApp creates the app!
+func CreateApp(_ *options.App) (*App, error) {
+ // result := w32.MessageBox(0,
+ // `Wails applications will not build without the correct build tags.
+ //Please use "wails build" or press "OK" to open the documentation on how to use "go build"`,
+ // "Error",
+ // w32.MB_ICONERROR|w32.MB_OKCANCEL)
+ // if result == 1 {
+ // exec.Command("rundll32", "url.dll,FileProtocolHandler", "https://wails.io").Start()
+ // }
+
+ err := fmt.Errorf(`Wails applications will not build without the correct build tags.`)
+
+ return nil, err
+}
diff --git a/v2/internal/appng/app_default_windows.go b/v2/internal/appng/app_default_windows.go
new file mode 100644
index 000000000..64ac79aa7
--- /dev/null
+++ b/v2/internal/appng/app_default_windows.go
@@ -0,0 +1,30 @@
+//go:build !dev && !production && !bindings && windows
+
+package appng
+
+import (
+ "os/exec"
+
+ "github.com/leaanthony/winc/w32"
+ "github.com/wailsapp/wails/v2/pkg/options"
+)
+
+// App defines a Wails application structure
+type App struct{}
+
+func (a *App) Run() error {
+ return nil
+}
+
+// CreateApp creates the app!
+func CreateApp(_ *options.App) (*App, error) {
+ result := w32.MessageBox(0,
+ `Wails applications will not build without the correct build tags.
+Please use "wails build" or press "OK" to open the documentation on how to use "go build"`,
+ "Error",
+ w32.MB_ICONERROR|w32.MB_OKCANCEL)
+ if result == 1 {
+ exec.Command("rundll32", "url.dll,FileProtocolHandler", "https://wails.io/docs/guides/manual-builds").Start()
+ }
+ return nil, nil
+}
diff --git a/v2/internal/appng/app_dev.go b/v2/internal/appng/app_dev.go
new file mode 100644
index 000000000..cc463bb88
--- /dev/null
+++ b/v2/internal/appng/app_dev.go
@@ -0,0 +1,171 @@
+//go:build dev
+// +build dev
+
+package appng
+
+import (
+ "context"
+ "flag"
+ "github.com/wailsapp/wails/v2/internal/binding"
+ "github.com/wailsapp/wails/v2/internal/frontend"
+ "github.com/wailsapp/wails/v2/internal/frontend/desktop"
+ "github.com/wailsapp/wails/v2/internal/frontend/devserver"
+ "github.com/wailsapp/wails/v2/internal/frontend/dispatcher"
+ "github.com/wailsapp/wails/v2/internal/frontend/runtime"
+ "github.com/wailsapp/wails/v2/internal/fs"
+ "github.com/wailsapp/wails/v2/internal/logger"
+ "github.com/wailsapp/wails/v2/internal/menumanager"
+ "github.com/wailsapp/wails/v2/internal/project"
+ "github.com/wailsapp/wails/v2/internal/signal"
+ pkglogger "github.com/wailsapp/wails/v2/pkg/logger"
+ "github.com/wailsapp/wails/v2/pkg/options"
+ "os"
+ "path/filepath"
+)
+
+// App defines a Wails application structure
+type App struct {
+ frontend frontend.Frontend
+ logger *logger.Logger
+ signal *signal.Manager
+ options *options.App
+
+ menuManager *menumanager.Manager
+
+ // Indicates if the app is in debug mode
+ debug bool
+
+ // OnStartup/OnShutdown
+ startupCallback func(ctx context.Context)
+ shutdownCallback func(ctx context.Context)
+ ctx context.Context
+}
+
+func (a *App) Run() error {
+ err := a.frontend.Run(a.ctx)
+ if a.shutdownCallback != nil {
+ a.shutdownCallback(a.ctx)
+ }
+ return err
+}
+
+// CreateApp creates the app!
+func CreateApp(appoptions *options.App) (*App, error) {
+ var err error
+
+ ctx := context.WithValue(context.Background(), "debug", true)
+
+ // Set up logger
+ myLogger := logger.New(appoptions.Logger)
+ myLogger.SetLogLevel(appoptions.LogLevel)
+
+ // Check for CLI Flags
+ assetdir := flag.String("assetdir", "", "Directory to serve assets")
+ devServerURL := flag.String("devserverurl", "", "URL of development server")
+ loglevel := flag.String("loglevel", "debug", "Loglevel to use - Trace, Debug, Info, Warning, Error")
+ flag.Parse()
+ if devServerURL != nil && *devServerURL != "" {
+ ctx = context.WithValue(ctx, "devserverurl", *devServerURL)
+ }
+ if assetdir != nil && *assetdir != "" {
+ ctx = context.WithValue(ctx, "assetdir", *assetdir)
+ }
+
+ if loglevel != nil && *loglevel != "" {
+ level, err := pkglogger.StringToLogLevel(*loglevel)
+ if err != nil {
+ return nil, err
+ }
+ myLogger.SetLogLevel(level)
+ }
+
+ // Attach logger to context
+ ctx = context.WithValue(ctx, "logger", myLogger)
+
+ // Preflight checks
+ err = PreflightChecks(appoptions, myLogger)
+ if err != nil {
+ return nil, err
+ }
+
+ // Merge default options
+ options.MergeDefaults(appoptions)
+
+ var menuManager *menumanager.Manager
+
+ // Process the application menu
+ if appoptions.Menu != nil {
+ // Create the menu manager
+ menuManager = menumanager.NewManager()
+ err = menuManager.SetApplicationMenu(appoptions.Menu)
+ if err != nil {
+ return nil, err
+ }
+ }
+
+ // Create binding exemptions - Ugly hack. There must be a better way
+ bindingExemptions := []interface{}{appoptions.OnStartup, appoptions.OnShutdown, appoptions.OnDomReady}
+ appBindings := binding.NewBindings(myLogger, appoptions.Bind, bindingExemptions)
+
+ err = generateBindings(appBindings)
+ if err != nil {
+ return nil, err
+ }
+ eventHandler := runtime.NewEvents(myLogger)
+ ctx = context.WithValue(ctx, "events", eventHandler)
+ messageDispatcher := dispatcher.NewDispatcher(myLogger, appBindings, eventHandler)
+
+ // Create the frontends and register to event handler
+ desktopFrontend := desktop.NewFrontend(ctx, appoptions, myLogger, appBindings, messageDispatcher)
+ appFrontend := devserver.NewFrontend(ctx, appoptions, myLogger, appBindings, messageDispatcher, menuManager, desktopFrontend)
+ eventHandler.AddFrontend(appFrontend)
+ eventHandler.AddFrontend(desktopFrontend)
+
+ result := &App{
+ ctx: ctx,
+ frontend: appFrontend,
+ logger: myLogger,
+ menuManager: menuManager,
+ startupCallback: appoptions.OnStartup,
+ shutdownCallback: appoptions.OnShutdown,
+ debug: true,
+ }
+
+ result.options = appoptions
+
+ return result, nil
+
+}
+
+func generateBindings(bindings *binding.Bindings) error {
+
+ cwd, err := os.Getwd()
+ if err != nil {
+ return err
+ }
+ projectConfig, err := project.Load(cwd)
+ if err != nil {
+ return err
+ }
+
+ targetDir := filepath.Join(projectConfig.WailsJSDir, "wailsjs", "go")
+ err = os.RemoveAll(targetDir)
+ if err != nil {
+ return err
+ }
+ _ = fs.MkDirs(targetDir)
+ modelsFile := filepath.Join(targetDir, "models.ts")
+ err = bindings.WriteTS(modelsFile)
+ if err != nil {
+ return err
+ }
+
+ // Write backend method wrappers
+ bindingsFilename := filepath.Join(targetDir, "bindings.js")
+ err = bindings.GenerateBackendJS(bindingsFilename, false)
+ if err != nil {
+ return err
+ }
+ return nil
+
+}
diff --git a/v2/internal/appng/app_production.go b/v2/internal/appng/app_production.go
new file mode 100644
index 000000000..7e404d359
--- /dev/null
+++ b/v2/internal/appng/app_production.go
@@ -0,0 +1,101 @@
+//go:build production
+// +build production
+
+package appng
+
+import (
+ "context"
+ "github.com/wailsapp/wails/v2/internal/binding"
+ "github.com/wailsapp/wails/v2/internal/frontend"
+ "github.com/wailsapp/wails/v2/internal/frontend/desktop"
+ "github.com/wailsapp/wails/v2/internal/frontend/dispatcher"
+ "github.com/wailsapp/wails/v2/internal/frontend/runtime"
+ "github.com/wailsapp/wails/v2/internal/logger"
+ "github.com/wailsapp/wails/v2/internal/menumanager"
+ "github.com/wailsapp/wails/v2/internal/signal"
+ "github.com/wailsapp/wails/v2/pkg/options"
+)
+
+// App defines a Wails application structure
+type App struct {
+ frontend frontend.Frontend
+ logger *logger.Logger
+ signal *signal.Manager
+ options *options.App
+
+ menuManager *menumanager.Manager
+
+ // Indicates if the app is in debug mode
+ debug bool
+
+ // OnStartup/OnShutdown
+ startupCallback func(ctx context.Context)
+ shutdownCallback func(ctx context.Context)
+ ctx context.Context
+}
+
+func (a *App) Run() error {
+ err := a.frontend.Run(a.ctx)
+ if a.shutdownCallback != nil {
+ a.shutdownCallback(a.ctx)
+ }
+ return err
+}
+
+// CreateApp creates the app!
+func CreateApp(appoptions *options.App) (*App, error) {
+ var err error
+
+ ctx := context.Background()
+
+ // Merge default options
+ options.MergeDefaults(appoptions)
+
+ // Set up logger
+ myLogger := logger.New(appoptions.Logger)
+ myLogger.SetLogLevel(appoptions.LogLevel)
+
+ // Preflight Checks
+ err = PreflightChecks(appoptions, myLogger)
+ if err != nil {
+ return nil, err
+ }
+
+ // Create the menu manager
+ menuManager := menumanager.NewManager()
+
+ // Process the application menu
+ if appoptions.Menu != nil {
+ err = menuManager.SetApplicationMenu(appoptions.Menu)
+ if err != nil {
+ return nil, err
+ }
+ }
+
+ // Create binding exemptions - Ugly hack. There must be a better way
+ bindingExemptions := []interface{}{appoptions.OnStartup, appoptions.OnShutdown, appoptions.OnDomReady}
+ appBindings := binding.NewBindings(myLogger, appoptions.Bind, bindingExemptions)
+ eventHandler := runtime.NewEvents(myLogger)
+ ctx = context.WithValue(ctx, "events", eventHandler)
+ messageDispatcher := dispatcher.NewDispatcher(myLogger, appBindings, eventHandler)
+
+ appFrontend := desktop.NewFrontend(ctx, appoptions, myLogger, appBindings, messageDispatcher)
+ eventHandler.AddFrontend(appFrontend)
+
+ result := &App{
+ ctx: ctx,
+ frontend: appFrontend,
+ logger: myLogger,
+ menuManager: menuManager,
+ startupCallback: appoptions.OnStartup,
+ shutdownCallback: appoptions.OnShutdown,
+ debug: false,
+ }
+
+ result.options = appoptions
+
+ result.ctx = context.WithValue(result.ctx, "debug", result.debug)
+
+ return result, nil
+
+}
diff --git a/v2/internal/appng/app_windows.go b/v2/internal/appng/app_windows.go
new file mode 100644
index 000000000..644cd728e
--- /dev/null
+++ b/v2/internal/appng/app_windows.go
@@ -0,0 +1,27 @@
+//go:build windows && !bindings
+
+package appng
+
+import (
+ "github.com/wailsapp/wails/v2/internal/ffenestri/windows/wv2runtime"
+ "github.com/wailsapp/wails/v2/internal/logger"
+ "github.com/wailsapp/wails/v2/pkg/options"
+)
+
+func PreflightChecks(options *options.App, logger *logger.Logger) error {
+
+ _ = options
+
+ // Process the webview2 runtime situation. We can pass a strategy in via the `webview2` flag for `wails build`.
+ // This will determine how wv2runtime.Process will handle a lack of valid runtime.
+ installedVersion, err := wv2runtime.Process()
+ if installedVersion != nil {
+ logger.Debug("WebView2 Runtime installed: Name: '%s' Version:'%s' Location:'%s'. Minimum version required: %s.",
+ installedVersion.Name, installedVersion.Version, installedVersion.Location, wv2runtime.MinimumRuntimeVersion)
+ }
+ if err != nil {
+ return err
+ }
+
+ return nil
+}
diff --git a/v2/internal/assetdb/assetdb.go b/v2/internal/assetdb/assetdb.go
new file mode 100644
index 000000000..54892952e
--- /dev/null
+++ b/v2/internal/assetdb/assetdb.go
@@ -0,0 +1,112 @@
+package assetdb
+
+import (
+ "fmt"
+ "strings"
+ "unsafe"
+)
+
+// AssetDB is a database for assets encoded as byte slices
+type AssetDB struct {
+ db map[string][]byte
+}
+
+// NewAssetDB creates a new AssetDB and initialises a blank db
+func NewAssetDB() *AssetDB {
+ return &AssetDB{
+ db: make(map[string][]byte),
+ }
+}
+
+// AddAsset saves the given byte slice under the given name
+func (a *AssetDB) AddAsset(name string, data []byte) {
+ a.db[name] = data
+}
+
+// Remove removes the named asset
+func (a *AssetDB) Remove(name string) {
+ delete(a.db, name)
+}
+
+// Asset retrieves the byte slice for the given name
+func (a *AssetDB) Read(name string) ([]byte, error) {
+ result := a.db[name]
+ if result == nil {
+ return nil, fmt.Errorf("asset '%s' not found", name)
+ }
+ return result, nil
+}
+
+// AssetAsString returns the asset as a string.
+// It also returns a boolean indicating whether the asset existed or not.
+func (a *AssetDB) String(name string) (string, error) {
+ asset, err := a.Read(name)
+ if err != nil {
+ return "", err
+ }
+ return *(*string)(unsafe.Pointer(&asset)), nil
+}
+
+func (a *AssetDB) Dump() {
+ fmt.Printf("Assets:\n")
+ for k, _ := range a.db {
+ fmt.Println(k)
+ }
+}
+
+// Serialize converts the entire database to a file that when compiled will
+// reconstruct the AssetDB during init()
+// name: name of the asset.AssetDB instance
+// pkg: package name placed at the top of the file
+func (a *AssetDB) Serialize(name, pkg string) string {
+ var cdata strings.Builder
+ // Set buffer size to 4k
+ cdata.Grow(4096)
+
+ // Write header
+ header := `// DO NOT EDIT - Generated automatically
+package %s
+
+import "github.com/wailsapp/wails/v2/internal/assetdb"
+
+var (
+ %s *assetdb.AssetDB = assetdb.NewAssetDB()
+)
+
+// AssetsDB is a clean interface to the assetdb.AssetDB struct
+type AssetsDB interface {
+ Read(string) ([]byte, error)
+ String(string) (string, error)
+}
+
+// Assets returns the asset database
+func Assets() AssetsDB {
+ return %s
+}
+
+func init() {
+`
+ cdata.WriteString(fmt.Sprintf(header, pkg, name, name))
+
+ for aname, bytes := range a.db {
+ cdata.WriteString(fmt.Sprintf("\t%s.AddAsset(\"%s\", []byte{",
+ name,
+ aname))
+
+ l := len(bytes)
+ if l == 0 {
+ cdata.WriteString("0x00})\n")
+ continue
+ }
+
+ // Convert each byte to hex
+ for _, b := range bytes[:l-1] {
+ cdata.WriteString(fmt.Sprintf("0x%x, ", b))
+ }
+ cdata.WriteString(fmt.Sprintf("0x%x})\n", bytes[l-1]))
+ }
+
+ cdata.WriteString(`}`)
+
+ return cdata.String()
+}
diff --git a/v2/internal/assetdb/assetdb_test.go b/v2/internal/assetdb/assetdb_test.go
new file mode 100644
index 000000000..b3f34b9fd
--- /dev/null
+++ b/v2/internal/assetdb/assetdb_test.go
@@ -0,0 +1,70 @@
+package assetdb
+
+import "testing"
+import "github.com/matryer/is"
+
+func TestExistsAsBytes(t *testing.T) {
+
+ is := is.New(t)
+
+ var helloworld = []byte{72, 101, 108, 108, 111, 44, 32, 87, 111, 114, 108, 100, 33}
+
+ db := NewAssetDB()
+ db.AddAsset("hello", helloworld)
+
+ result, err := db.Read("hello")
+
+ is.True(err == nil)
+ is.Equal(result, helloworld)
+}
+
+func TestNotExistsAsBytes(t *testing.T) {
+
+ is := is.New(t)
+
+ var helloworld = []byte{72, 101, 108, 108, 111, 44, 32, 87, 111, 114, 108, 100, 33}
+
+ db := NewAssetDB()
+ db.AddAsset("hello4", helloworld)
+
+ result, err := db.Read("hello")
+
+ is.True(err != nil)
+ is.True(result == nil)
+}
+
+func TestExistsAsString(t *testing.T) {
+
+ is := is.New(t)
+
+ var helloworld = []byte{72, 101, 108, 108, 111, 44, 32, 87, 111, 114, 108, 100, 33}
+
+ db := NewAssetDB()
+ db.AddAsset("hello", helloworld)
+
+ result, err := db.String("hello")
+
+ // Ensure it exists
+ is.True(err == nil)
+
+ // Ensure the string is the same as the byte slice
+ is.Equal(result, "Hello, World!")
+}
+
+func TestNotExistsAsString(t *testing.T) {
+
+ is := is.New(t)
+
+ var helloworld = []byte{72, 101, 108, 108, 111, 44, 32, 87, 111, 114, 108, 100, 33}
+
+ db := NewAssetDB()
+ db.AddAsset("hello", helloworld)
+
+ result, err := db.String("help")
+
+ // Ensure it doesn't exist
+ is.True(err != nil)
+
+ // Ensure the string is blank
+ is.Equal(result, "")
+}
diff --git a/v2/internal/assetdb/filesystem.go b/v2/internal/assetdb/filesystem.go
new file mode 100644
index 000000000..48acb713f
--- /dev/null
+++ b/v2/internal/assetdb/filesystem.go
@@ -0,0 +1,176 @@
+// +build !desktop
+package assetdb
+
+import (
+ "errors"
+ "io"
+ "net/http"
+ "os"
+ "path"
+ "sort"
+ "strings"
+ "time"
+)
+
+var errWhence = errors.New("Seek: invalid whence")
+var errOffset = errors.New("Seek: invalid offset")
+
+// Open implements the http.FileSystem interface for the AssetDB
+func (a *AssetDB) Open(name string) (http.File, error) {
+ if name == "/" || name == "" {
+ return &Entry{name: "/", dir: true, db: a}, nil
+ }
+
+ if data, ok := a.db[name]; ok {
+ return &Entry{name: name, data: data, size: len(data)}, nil
+ } else {
+ for n, _ := range a.db {
+ if strings.HasPrefix(n, name+"/") {
+ return &Entry{name: name, db: a, dir: true}, nil
+ }
+ }
+ }
+ return &Entry{}, os.ErrNotExist
+}
+
+// readdir returns the directory entries for the requested directory
+func (a *AssetDB) readdir(name string) ([]os.FileInfo, error) {
+ dir := name
+ var ents []string
+
+ fim := make(map[string]os.FileInfo)
+ for fn, data := range a.db {
+ if strings.HasPrefix(fn, dir) {
+ pieces := strings.Split(fn[len(dir)+1:], "/")
+ if len(pieces) == 1 {
+ fim[pieces[0]] = FI{name: pieces[0], dir: false, size: len(data)}
+ ents = append(ents, pieces[0])
+ } else {
+ fim[pieces[0]] = FI{name: pieces[0], dir: true, size: -1}
+ ents = append(ents, pieces[0])
+ }
+ }
+ }
+
+ if len(ents) == 0 {
+ return nil, os.ErrNotExist
+ }
+
+ sort.Strings(ents)
+ var list []os.FileInfo
+ for _, dir := range ents {
+ list = append(list, fim[dir])
+ }
+ return list, nil
+}
+
+// Entry implements the http.File interface to allow for
+// use in the http.FileSystem implementation of AssetDB
+type Entry struct {
+ name string
+ data []byte
+ dir bool
+ size int
+ db *AssetDB
+ off int
+}
+
+// Close is a noop
+func (e Entry) Close() error {
+ return nil
+}
+
+// Read fills the slice provided returning how many bytes were written
+// and any errors encountered
+func (e *Entry) Read(p []byte) (n int, err error) {
+ if e.off >= e.size {
+ return 0, io.EOF
+ }
+ numout := len(p)
+ if numout > e.size {
+ numout = e.size
+ }
+ for i := 0; i < numout; i++ {
+ p[i] = e.data[e.off+i]
+ }
+ e.off += numout
+ n = int(numout)
+ err = nil
+ return
+}
+
+// Seek seeks to the specified offset from the location specified by whence
+func (e *Entry) Seek(offset int64, whence int) (int64, error) {
+ switch whence {
+ default:
+ return 0, errWhence
+ case io.SeekStart:
+ offset += 0
+ case io.SeekCurrent:
+ offset += int64(e.off)
+ case io.SeekEnd:
+ offset += int64(e.size)
+ }
+
+ if offset < 0 {
+ return 0, errOffset
+ }
+ e.off = int(offset)
+ return offset, nil
+}
+
+// Readdir returns the directory entries inside this entry if it is a directory
+func (e Entry) Readdir(count int) ([]os.FileInfo, error) {
+ ents := []os.FileInfo{}
+ if !e.dir {
+ return ents, errors.New("Not a directory")
+ }
+ return e.db.readdir(e.name)
+}
+
+// Stat returns information about this directory entry
+func (e Entry) Stat() (os.FileInfo, error) {
+ return FI{e.name, e.size, e.dir}, nil
+}
+
+// FI is the AssetDB implementation of os.FileInfo.
+type FI struct {
+ name string
+ size int
+ dir bool
+}
+
+// IsDir returns true if this is a directory
+func (fi FI) IsDir() bool {
+ return fi.dir
+}
+
+// ModTime always returns now
+func (fi FI) ModTime() time.Time {
+ return time.Time{}
+}
+
+// Mode returns the file as readonly and directories
+// as world writeable and executable
+func (fi FI) Mode() os.FileMode {
+ if fi.IsDir() {
+ return 0755 | os.ModeDir
+ }
+ return 0444
+}
+
+// Name returns the name of this object without
+// any leading slashes
+func (fi FI) Name() string {
+ return path.Base(fi.name)
+}
+
+// Size returns the size of this item
+func (fi FI) Size() int64 {
+ return int64(fi.size)
+}
+
+// Sys returns nil
+func (fi FI) Sys() interface{} {
+ return nil
+}
diff --git a/v2/internal/assetdb/filesystem_test.go b/v2/internal/assetdb/filesystem_test.go
new file mode 100644
index 000000000..1c2ed94a4
--- /dev/null
+++ b/v2/internal/assetdb/filesystem_test.go
@@ -0,0 +1,108 @@
+package assetdb
+
+import (
+ "fmt"
+ "os"
+ "testing"
+
+ "github.com/matryer/is"
+)
+
+func TestOpenLeadingSlash(t *testing.T) {
+ is := is.New(t)
+
+ var helloworld = []byte{72, 101, 108, 108, 111, 44, 32, 87, 111, 114, 108, 100, 33}
+
+ db := NewAssetDB()
+ db.AddAsset("/hello", helloworld)
+
+ file, err := db.Open("/hello")
+ // Ensure it does exist
+ is.True(err == nil)
+
+ buff := make([]byte, len(helloworld))
+ n, err := file.Read(buff)
+ fmt.Printf("Error %v\n", err)
+ is.True(err == nil)
+ is.Equal(n, len(helloworld))
+ result := string(buff)
+
+ // Ensure the string is blank
+ is.Equal(result, string(helloworld))
+}
+
+func TestOpen(t *testing.T) {
+ is := is.New(t)
+
+ var helloworld = []byte{72, 101, 108, 108, 111, 44, 32, 87, 111, 114, 108, 100, 33}
+
+ db := NewAssetDB()
+ db.AddAsset("/hello", helloworld)
+
+ file, err := db.Open("/hello")
+
+ // Ensure it does exist
+ is.True(err == nil)
+
+ buff := make([]byte, len(helloworld))
+ n, err := file.Read(buff)
+ is.True(err == nil)
+ is.Equal(n, len(helloworld))
+ result := string(buff)
+
+ // Ensure the string is blank
+ is.Equal(result, string(helloworld))
+}
+
+func TestReaddir(t *testing.T) {
+ is := is.New(t)
+
+ var helloworld = []byte{72, 101, 108, 108, 111, 44, 32, 87, 111, 114, 108, 100, 33}
+
+ db := NewAssetDB()
+ db.AddAsset("/hello", helloworld)
+ db.AddAsset("/directory/hello", helloworld)
+ db.AddAsset("/directory/subdirectory/hello", helloworld)
+
+ dir, err := db.Open("/doesntexist")
+ is.True(err == os.ErrNotExist)
+ ents, err := dir.Readdir(-1)
+ is.Equal([]os.FileInfo{}, ents)
+
+ dir, err = db.Open("/")
+ is.True(dir != nil)
+ is.True(err == nil)
+ ents, err = dir.Readdir(-1)
+ is.True(err == nil)
+ is.Equal(3, len(ents))
+}
+
+func TestReaddirSubdirectory(t *testing.T) {
+ is := is.New(t)
+
+ var helloworld = []byte{72, 101, 108, 108, 111, 44, 32, 87, 111, 114, 108, 100, 33}
+
+ db := NewAssetDB()
+ db.AddAsset("/hello", helloworld)
+ db.AddAsset("/directory/hello", helloworld)
+ db.AddAsset("/directory/subdirectory/hello", helloworld)
+
+ expected := []os.FileInfo{
+ FI{name: "hello", dir: false, size: len(helloworld)},
+ FI{name: "subdirectory", dir: true, size: -1},
+ }
+
+ dir, err := db.Open("/directory")
+ is.True(dir != nil)
+ is.True(err == nil)
+ ents, err := dir.Readdir(-1)
+ is.Equal(expected, ents)
+
+ // Check sub-subdirectory
+ dir, err = db.Open("/directory/subdirectory")
+ is.True(dir != nil)
+ is.True(err == nil)
+ ents, err = dir.Readdir(-1)
+ is.True(err == nil)
+ is.Equal([]os.FileInfo{FI{name: "hello", size: len(helloworld)}}, ents)
+}
diff --git a/v2/internal/bind/bind.go b/v2/internal/bind/bind.go
new file mode 100644
index 000000000..156fd4ce4
--- /dev/null
+++ b/v2/internal/bind/bind.go
@@ -0,0 +1,9 @@
+package bind
+
+func IsStructPointer(value interface{}) bool {
+ switch t := value.(type) {
+ default:
+ println(t)
+ }
+ return false
+}
diff --git a/v2/internal/binding/assets/package.json b/v2/internal/binding/assets/package.json
new file mode 100644
index 000000000..1b82716c0
--- /dev/null
+++ b/v2/internal/binding/assets/package.json
@@ -0,0 +1,10 @@
+{
+ "name": "go",
+ "version": "1.0.0",
+ "description": "Package to wrap your bound go methods",
+ "main": "bindings.js",
+ "types": "bindings.d.ts",
+ "scripts": {},
+ "author": "",
+ "license": "ISC"
+}
\ No newline at end of file
diff --git a/v2/internal/binding/binding.go b/v2/internal/binding/binding.go
new file mode 100755
index 000000000..ef33d858f
--- /dev/null
+++ b/v2/internal/binding/binding.go
@@ -0,0 +1,88 @@
+package binding
+
+import (
+ "fmt"
+ "github.com/leaanthony/typescriptify-golang-structs/typescriptify"
+ "reflect"
+ "runtime"
+ "strings"
+
+ "github.com/leaanthony/slicer"
+ "github.com/wailsapp/wails/v2/internal/logger"
+)
+
+type Bindings struct {
+ db *DB
+ logger logger.CustomLogger
+ exemptions slicer.StringSlicer
+
+ // Typescript writer
+ converter *typescriptify.TypeScriptify
+}
+
+// NewBindings returns a new Bindings object
+func NewBindings(logger *logger.Logger, structPointersToBind []interface{}, exemptions []interface{}) *Bindings {
+ result := &Bindings{
+ db: newDB(),
+ logger: logger.CustomLogger("Bindings"),
+ converter: typescriptify.New(),
+ }
+
+ // No backups
+ result.converter.WithBackupDir("")
+
+ // Hack for TS compilation error
+ result.converter.AddImport("export {};")
+
+ for _, exemption := range exemptions {
+ if exemptions == nil {
+ continue
+ }
+ name := runtime.FuncForPC(reflect.ValueOf(exemption).Pointer()).Name()
+ // Yuk yuk yuk! Is there a better way?
+ name = strings.TrimSuffix(name, "-fm")
+ result.exemptions.Add(name)
+ }
+
+ // Add the structs to bind
+ for _, ptr := range structPointersToBind {
+ err := result.Add(ptr)
+ if err != nil {
+ logger.Fatal("Error during binding: " + err.Error())
+ }
+ }
+
+ return result
+}
+
+// Add the given struct methods to the Bindings
+func (b *Bindings) Add(structPtr interface{}) error {
+
+ methods, err := b.getMethods(structPtr)
+ if err != nil {
+ return fmt.Errorf("cannot bind value to app: %s", err.Error())
+ }
+
+ for _, method := range methods {
+ splitName := strings.Split(method.Name, ".")
+ packageName := splitName[0]
+ structName := splitName[1]
+ methodName := splitName[2]
+
+ // Add it as a regular method
+ b.db.AddMethod(packageName, structName, methodName, method)
+ }
+ return nil
+}
+
+func (b *Bindings) WriteTS(filename string) error {
+ return b.converter.ConvertToFile(filename)
+}
+
+func (b *Bindings) DB() *DB {
+ return b.db
+}
+
+func (b *Bindings) ToJSON() (string, error) {
+ return b.db.ToJSON()
+}
diff --git a/v2/internal/binding/boundMethod.go b/v2/internal/binding/boundMethod.go
new file mode 100644
index 000000000..f6ffdb600
--- /dev/null
+++ b/v2/internal/binding/boundMethod.go
@@ -0,0 +1,100 @@
+package binding
+
+import (
+ "encoding/json"
+ "fmt"
+ "reflect"
+)
+
+// BoundMethod defines all the data related to a Go method that is
+// bound to the Wails application
+type BoundMethod struct {
+ Name string `json:"name"`
+ Inputs []*Parameter `json:"inputs,omitempty"`
+ Outputs []*Parameter `json:"outputs,omitempty"`
+ Comments string `json:"comments,omitempty"`
+ Method reflect.Value `json:"-"`
+}
+
+// InputCount returns the number of inputs this bound method has
+func (b *BoundMethod) InputCount() int {
+ return len(b.Inputs)
+}
+
+// OutputCount returns the number of outputs this bound method has
+func (b *BoundMethod) OutputCount() int {
+ return len(b.Outputs)
+}
+
+// ParseArgs method converts the input json into the types expected by the method
+func (b *BoundMethod) ParseArgs(args []json.RawMessage) ([]interface{}, error) {
+
+ result := make([]interface{}, b.InputCount())
+ if len(args) != b.InputCount() {
+ return nil, fmt.Errorf("received %d arguments to method '%s', expected %d", len(args), b.Name, b.InputCount())
+ }
+ for index, arg := range args {
+ typ := b.Inputs[index].reflectType
+ inputValue := reflect.New(typ).Interface()
+ err := json.Unmarshal(arg, inputValue)
+ if err != nil {
+ return nil, err
+ }
+ if inputValue == nil {
+ result[index] = reflect.Zero(typ).Interface()
+ } else {
+ result[index] = reflect.ValueOf(inputValue).Elem().Interface()
+ }
+ }
+ return result, nil
+}
+
+// Call will attempt to call this bound method with the given args
+func (b *BoundMethod) Call(args []interface{}) (interface{}, error) {
+ // Check inputs
+ expectedInputLength := len(b.Inputs)
+ actualInputLength := len(args)
+ if expectedInputLength != actualInputLength {
+ return nil, fmt.Errorf("%s takes %d inputs. Received %d", b.Name, expectedInputLength, actualInputLength)
+ }
+
+ /** Convert inputs to reflect values **/
+
+ // Create slice for the input arguments to the method call
+ callArgs := make([]reflect.Value, expectedInputLength)
+
+ // Iterate over given arguments
+ for index, arg := range args {
+ // Save the converted argument
+ callArgs[index] = reflect.ValueOf(arg)
+ }
+
+ // Do the call
+ callResults := b.Method.Call(callArgs)
+
+ //** Check results **//
+ var returnValue interface{}
+ var err error
+
+ switch b.OutputCount() {
+ case 1:
+ // Loop over results and determine if the result
+ // is an error or not
+ for _, result := range callResults {
+ interfac := result.Interface()
+ temp, ok := interfac.(error)
+ if ok {
+ err = temp
+ } else {
+ returnValue = interfac
+ }
+ }
+ case 2:
+ returnValue = callResults[0].Interface()
+ if temp, ok := callResults[1].Interface().(error); ok {
+ err = temp
+ }
+ }
+
+ return returnValue, err
+}
diff --git a/v2/internal/binding/db.go b/v2/internal/binding/db.go
new file mode 100644
index 000000000..37c369720
--- /dev/null
+++ b/v2/internal/binding/db.go
@@ -0,0 +1,104 @@
+package binding
+
+import (
+ "encoding/json"
+ "sync"
+ "unsafe"
+)
+
+// DB is our database of method bindings
+type DB struct {
+ // map[packagename] -> map[structname] -> map[methodname]*method
+ store map[string]map[string]map[string]*BoundMethod
+
+ // This uses fully qualified method names as a shortcut for store traversal.
+ // It used for performance gains at runtime
+ methodMap map[string]*BoundMethod
+
+ // Lock to ensure sync access to the data
+ lock sync.RWMutex
+}
+
+func newDB() *DB {
+ return &DB{
+ store: make(map[string]map[string]map[string]*BoundMethod),
+ methodMap: make(map[string]*BoundMethod),
+ }
+}
+
+// GetMethodFromStore returns the method for the given package/struct/method names
+// nil is returned if any one of those does not exist
+func (d *DB) GetMethodFromStore(packageName string, structName string, methodName string) *BoundMethod {
+
+ // Lock the db whilst processing and unlock on return
+ d.lock.RLock()
+ defer d.lock.RUnlock()
+
+ structMap, exists := d.store[packageName]
+ if !exists {
+ return nil
+ }
+ methodMap, exists := structMap[structName]
+ if !exists {
+ return nil
+ }
+ return methodMap[methodName]
+}
+
+// GetMethod returns the method for the given qualified method name
+// qualifiedMethodName is "packagename.structname.methodname"
+func (d *DB) GetMethod(qualifiedMethodName string) *BoundMethod {
+
+ // Lock the db whilst processing and unlock on return
+ d.lock.RLock()
+ defer d.lock.RUnlock()
+
+ return d.methodMap[qualifiedMethodName]
+}
+
+// AddMethod adds the given method definition to the db using the given qualified path: packageName.structName.methodName
+func (d *DB) AddMethod(packageName string, structName string, methodName string, methodDefinition *BoundMethod) {
+
+ // TODO: Validate inputs?
+
+ // Lock the db whilst processing and unlock on return
+ d.lock.Lock()
+ defer d.lock.Unlock()
+
+ // Get the map associated with the package name
+ structMap, exists := d.store[packageName]
+ if !exists {
+ // Create a new map for this packagename
+ d.store[packageName] = make(map[string]map[string]*BoundMethod)
+ structMap = d.store[packageName]
+ }
+
+ // Get the map associated with the struct name
+ methodMap, exists := structMap[structName]
+ if !exists {
+ // Create a new map for this packagename
+ structMap[structName] = make(map[string]*BoundMethod)
+ methodMap = structMap[structName]
+ }
+
+ // Store the method definition
+ methodMap[methodName] = methodDefinition
+
+ // Store in the methodMap
+ key := packageName + "." + structName + "." + methodName
+ d.methodMap[key] = methodDefinition
+
+}
+
+// ToJSON converts the method map to JSON
+func (d *DB) ToJSON() (string, error) {
+
+ // Lock the db whilst processing and unlock on return
+ d.lock.RLock()
+ defer d.lock.RUnlock()
+
+ bytes, err := json.Marshal(&d.store)
+
+ // Return zero copy string as this string will be read only
+ return *(*string)(unsafe.Pointer(&bytes)), err
+}
diff --git a/v2/internal/binding/generate.go b/v2/internal/binding/generate.go
new file mode 100644
index 000000000..dd90f2ae0
--- /dev/null
+++ b/v2/internal/binding/generate.go
@@ -0,0 +1,149 @@
+package binding
+
+import (
+ "bytes"
+ _ "embed"
+ "fmt"
+ "os"
+ "path/filepath"
+ "strings"
+
+ "github.com/wailsapp/wails/v2/internal/fs"
+
+ "github.com/leaanthony/slicer"
+)
+
+//go:embed assets/package.json
+var packageJSON []byte
+
+func (b *Bindings) GenerateBackendJS(targetfile string, isDevBindings bool) error {
+
+ store := b.db.store
+ var output bytes.Buffer
+
+ output.WriteString(`// @ts-check
+// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
+// This file is automatically generated. DO NOT EDIT
+`)
+
+ if isDevBindings {
+ json, err := b.ToJSON()
+ if err != nil {
+ return err
+ }
+ output.WriteString("window.wailsbindings = " + json + ";")
+ output.WriteString("\n")
+ }
+
+ output.WriteString(`const go = {`)
+ output.WriteString("\n")
+
+ var sortedPackageNames slicer.StringSlicer
+ for packageName := range store {
+ sortedPackageNames.Add(packageName)
+ }
+ sortedPackageNames.Sort()
+ sortedPackageNames.Each(func(packageName string) {
+ packages := store[packageName]
+ output.WriteString(fmt.Sprintf(" \"%s\": {", packageName))
+ output.WriteString("\n")
+ var sortedStructNames slicer.StringSlicer
+ for structName := range packages {
+ sortedStructNames.Add(structName)
+ }
+ sortedStructNames.Sort()
+
+ sortedStructNames.Each(func(structName string) {
+ structs := packages[structName]
+ output.WriteString(fmt.Sprintf(" \"%s\": {", structName))
+ output.WriteString("\n")
+
+ var sortedMethodNames slicer.StringSlicer
+ for methodName := range structs {
+ sortedMethodNames.Add(methodName)
+ }
+ sortedMethodNames.Sort()
+
+ sortedMethodNames.Each(func(methodName string) {
+ methodDetails := structs[methodName]
+ output.WriteString(" /**\n")
+ output.WriteString(" * " + methodName + "\n")
+ var args slicer.StringSlicer
+ for count, input := range methodDetails.Inputs {
+ arg := fmt.Sprintf("arg%d", count+1)
+ args.Add(arg)
+ output.WriteString(fmt.Sprintf(" * @param {%s} %s - Go Type: %s\n", goTypeToJSDocType(input.TypeName), arg, input.TypeName))
+ }
+ returnType := "Promise"
+ returnTypeDetails := ""
+ if methodDetails.OutputCount() > 0 {
+ firstType := goTypeToJSDocType(methodDetails.Outputs[0].TypeName)
+ returnType += "<" + firstType
+ if methodDetails.OutputCount() == 2 {
+ secondType := goTypeToJSDocType(methodDetails.Outputs[1].TypeName)
+ returnType += "|" + secondType
+ }
+ returnType += ">"
+ returnTypeDetails = " - Go Type: " + methodDetails.Outputs[0].TypeName
+ } else {
+ returnType = "Promise"
+ }
+ output.WriteString(" * @returns {" + returnType + "} " + returnTypeDetails + "\n")
+ output.WriteString(" */\n")
+ argsString := args.Join(", ")
+ output.WriteString(fmt.Sprintf(" \"%s\": (%s) => {", methodName, argsString))
+ output.WriteString("\n")
+ output.WriteString(fmt.Sprintf(" return window.go.%s.%s.%s(%s);", packageName, structName, methodName, argsString))
+ output.WriteString("\n")
+ output.WriteString(fmt.Sprintf(" },"))
+ output.WriteString("\n")
+
+ })
+
+ output.WriteString(" },\n")
+ })
+
+ output.WriteString(" },\n\n")
+ })
+
+ output.WriteString(`};
+export default go;`)
+ output.WriteString("\n")
+
+ dir := filepath.Dir(targetfile)
+ packageJsonFile := filepath.Join(dir, "package.json")
+ if !fs.FileExists(packageJsonFile) {
+ err := os.WriteFile(packageJsonFile, packageJSON, 0755)
+ if err != nil {
+ return err
+ }
+ }
+
+ return os.WriteFile(targetfile, output.Bytes(), 0755)
+}
+
+func goTypeToJSDocType(input string) string {
+ switch true {
+ case input == "string":
+ return "string"
+ case input == "error":
+ return "Error"
+ case
+ strings.HasPrefix(input, "int"),
+ strings.HasPrefix(input, "uint"),
+ strings.HasPrefix(input, "float"):
+ return "number"
+ case input == "bool":
+ return "boolean"
+ case input == "[]byte":
+ return "string"
+ case strings.HasPrefix(input, "[]"):
+ arrayType := goTypeToJSDocType(input[2:])
+ return "Array.<" + arrayType + ">"
+ default:
+ if strings.ContainsRune(input, '.') {
+ return strings.Split(input, ".")[1]
+ }
+ return "any"
+ }
+}
diff --git a/v2/internal/binding/generate_test.go b/v2/internal/binding/generate_test.go
new file mode 100644
index 000000000..e2751ceb5
--- /dev/null
+++ b/v2/internal/binding/generate_test.go
@@ -0,0 +1,87 @@
+package binding
+
+import (
+ "testing"
+)
+
+func Test_goTypeToJSDocType(t *testing.T) {
+
+ tests := []struct {
+ name string
+ input string
+ want string
+ }{
+ {
+ name: "string",
+ input: "string",
+ want: "string",
+ },
+ {
+ name: "error",
+ input: "error",
+ want: "Error",
+ },
+ {
+ name: "int",
+ input: "int",
+ want: "number",
+ },
+ {
+ name: "int32",
+ input: "int32",
+ want: "number",
+ },
+ {
+ name: "uint",
+ input: "uint",
+ want: "number",
+ },
+ {
+ name: "uint32",
+ input: "uint32",
+ want: "number",
+ },
+ {
+ name: "float32",
+ input: "float32",
+ want: "number",
+ },
+ {
+ name: "float64",
+ input: "float64",
+ want: "number",
+ },
+ {
+ name: "bool",
+ input: "bool",
+ want: "boolean",
+ },
+ {
+ name: "[]byte",
+ input: "[]byte",
+ want: "string",
+ },
+ {
+ name: "[]int",
+ input: "[]int",
+ want: "Array.",
+ },
+ {
+ name: "[]bool",
+ input: "[]bool",
+ want: "Array.",
+ },
+ {
+ name: "anything else",
+ input: "foo",
+ want: "any",
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ if got := goTypeToJSDocType(tt.input); got != tt.want {
+ t.Errorf("goTypeToJSDocType() = %v, want %v", got, tt.want)
+ }
+ })
+ }
+}
diff --git a/v2/internal/binding/parameter.go b/v2/internal/binding/parameter.go
new file mode 100644
index 000000000..ef10a24ec
--- /dev/null
+++ b/v2/internal/binding/parameter.go
@@ -0,0 +1,28 @@
+package binding
+
+import "reflect"
+
+// Parameter defines a Go method parameter
+type Parameter struct {
+ Name string `json:"name,omitempty"`
+ TypeName string `json:"type"`
+ reflectType reflect.Type
+}
+
+func newParameter(Name string, Type reflect.Type) *Parameter {
+ return &Parameter{
+ Name: Name,
+ TypeName: Type.String(),
+ reflectType: Type,
+ }
+}
+
+// IsType returns true if the given
+func (p *Parameter) IsType(typename string) bool {
+ return p.TypeName == typename
+}
+
+// IsError returns true if the parameter type is an error
+func (p *Parameter) IsError() bool {
+ return p.IsType("error")
+}
diff --git a/v2/internal/binding/reflect.go b/v2/internal/binding/reflect.go
new file mode 100755
index 000000000..3b79428f0
--- /dev/null
+++ b/v2/internal/binding/reflect.go
@@ -0,0 +1,120 @@
+package binding
+
+import (
+ "fmt"
+ "reflect"
+ "runtime"
+)
+
+// isStructPtr returns true if the value given is a
+// pointer to a struct
+func isStructPtr(value interface{}) bool {
+ return reflect.ValueOf(value).Kind() == reflect.Ptr &&
+ reflect.ValueOf(value).Elem().Kind() == reflect.Struct
+}
+
+// isFunction returns true if the given value is a function
+func isFunction(value interface{}) bool {
+ return reflect.ValueOf(value).Kind() == reflect.Func
+}
+
+// isStructPtr returns true if the value given is a struct
+func isStruct(value interface{}) bool {
+ return reflect.ValueOf(value).Kind() == reflect.Struct
+}
+
+func (b *Bindings) getMethods(value interface{}) ([]*BoundMethod, error) {
+
+ // Create result placeholder
+ var result []*BoundMethod
+
+ // Check type
+ if !isStructPtr(value) {
+
+ if isStruct(value) {
+ name := reflect.ValueOf(value).Type().Name()
+ return nil, fmt.Errorf("%s is a struct, not a pointer to a struct", name)
+ }
+
+ if isFunction(value) {
+ name := runtime.FuncForPC(reflect.ValueOf(value).Pointer()).Name()
+ return nil, fmt.Errorf("%s is a function, not a pointer to a struct. Wails v2 has deprecated the binding of functions. Please wrap your functions up in a struct and bind a pointer to that struct.", name)
+ }
+
+ return nil, fmt.Errorf("not a pointer to a struct.")
+ }
+
+ // Process Struct
+ structType := reflect.TypeOf(value)
+ structValue := reflect.ValueOf(value)
+ baseName := structType.String()[1:]
+
+ // Process Methods
+ for i := 0; i < structType.NumMethod(); i++ {
+ methodDef := structType.Method(i)
+ methodName := methodDef.Name
+ fullMethodName := baseName + "." + methodName
+ method := structValue.MethodByName(methodName)
+
+ methodReflectName := runtime.FuncForPC(methodDef.Func.Pointer()).Name()
+ if b.exemptions.Contains(methodReflectName) {
+ continue
+ }
+
+ // Create new method
+ boundMethod := &BoundMethod{
+ Name: fullMethodName,
+ Inputs: nil,
+ Outputs: nil,
+ Comments: "",
+ Method: method,
+ }
+
+ // Iterate inputs
+ methodType := method.Type()
+ inputParamCount := methodType.NumIn()
+ var inputs []*Parameter
+ for inputIndex := 0; inputIndex < inputParamCount; inputIndex++ {
+ input := methodType.In(inputIndex)
+ thisParam := newParameter("", input)
+
+ // Process struct pointer params
+ if input.Kind() == reflect.Ptr {
+ if input.Elem().Kind() == reflect.Struct {
+ typ := input.Elem()
+ a := reflect.New(typ)
+ s := reflect.Indirect(a).Interface()
+ b.converter.Add(s)
+ }
+ }
+
+ // Process struct params
+ if input.Kind() == reflect.Struct {
+ a := reflect.New(input)
+ s := reflect.Indirect(a).Interface()
+ b.converter.Add(s)
+ }
+
+ inputs = append(inputs, thisParam)
+ }
+
+ boundMethod.Inputs = inputs
+
+ // Iterate outputs
+ // TODO: Determine what to do about limiting return types
+ // especially around errors.
+ outputParamCount := methodType.NumOut()
+ var outputs []*Parameter
+ for outputIndex := 0; outputIndex < outputParamCount; outputIndex++ {
+ output := methodType.Out(outputIndex)
+ thisParam := newParameter("", output)
+ outputs = append(outputs, thisParam)
+ }
+ boundMethod.Outputs = outputs
+
+ // Save method in result
+ result = append(result, boundMethod)
+
+ }
+ return result, nil
+}
diff --git a/v2/internal/bridge/bridge.go b/v2/internal/bridge/bridge.go
new file mode 100644
index 000000000..1ea509d33
--- /dev/null
+++ b/v2/internal/bridge/bridge.go
@@ -0,0 +1,113 @@
+package bridge
+
+import (
+ "context"
+ "log"
+ "net/http"
+ "sync"
+
+ "github.com/wailsapp/wails/v2/internal/menumanager"
+
+ "github.com/wailsapp/wails/v2/internal/messagedispatcher"
+
+ "github.com/gorilla/websocket"
+ "github.com/wailsapp/wails/v2/internal/logger"
+)
+
+type Bridge struct {
+ upgrader websocket.Upgrader
+ server *http.Server
+ myLogger *logger.Logger
+
+ bindings string
+ dispatcher *messagedispatcher.Dispatcher
+
+ mu sync.Mutex
+ sessions map[string]*session
+
+ ctx context.Context
+ cancel context.CancelFunc
+
+ // Dialog client
+ dialog *messagedispatcher.DispatchClient
+
+ // Menus
+ menumanager *menumanager.Manager
+}
+
+func NewBridge(myLogger *logger.Logger) *Bridge {
+ result := &Bridge{
+ myLogger: myLogger,
+ upgrader: websocket.Upgrader{CheckOrigin: func(r *http.Request) bool { return true }},
+ sessions: make(map[string]*session),
+ }
+
+ myLogger.SetLogLevel(1)
+
+ ctx, cancel := context.WithCancel(context.Background())
+ result.ctx = ctx
+ result.cancel = cancel
+ result.server = &http.Server{Addr: ":34115"}
+ http.HandleFunc("/bridge", result.wsBridgeHandler)
+ return result
+}
+
+func (b *Bridge) Run(dispatcher *messagedispatcher.Dispatcher, menumanager *menumanager.Manager, bindings string, debug bool) error {
+
+ // Ensure we cancel the context when we shutdown
+ defer b.cancel()
+
+ b.bindings = bindings
+ b.dispatcher = dispatcher
+ b.menumanager = menumanager
+
+ // Setup dialog handler
+ dialogClient := NewDialogClient(b.myLogger)
+ b.dialog = dispatcher.RegisterClient(dialogClient)
+ dialogClient.dispatcher = b.dialog
+
+ b.myLogger.Info("Bridge mode started.")
+
+ err := b.server.ListenAndServe()
+ if err != nil && err != http.ErrServerClosed {
+ return err
+ }
+
+ return nil
+}
+
+func (b *Bridge) wsBridgeHandler(w http.ResponseWriter, r *http.Request) {
+ c, err := b.upgrader.Upgrade(w, r, nil)
+ if err != nil {
+ log.Print("upgrade:", err)
+ return
+ }
+
+ if err != nil {
+ http.Error(w, "Could not open websocket connection", http.StatusBadRequest)
+ }
+ b.myLogger.Info("Connection from frontend accepted [%s].", c.RemoteAddr().String())
+ b.startSession(c)
+
+}
+
+func (b *Bridge) startSession(conn *websocket.Conn) {
+
+ // Create a new session for this connection
+ s := newSession(conn, b.menumanager, b.bindings, b.dispatcher, b.myLogger, b.ctx)
+
+ // Setup the close handler
+ conn.SetCloseHandler(func(int, string) error {
+ b.myLogger.Info("Connection dropped [%s].", s.Identifier())
+ b.dispatcher.RemoveClient(s.client)
+ b.mu.Lock()
+ delete(b.sessions, s.Identifier())
+ b.mu.Unlock()
+ return nil
+ })
+
+ b.mu.Lock()
+ go s.start(len(b.sessions) == 0)
+ b.sessions[s.Identifier()] = s
+ b.mu.Unlock()
+}
diff --git a/v2/internal/bridge/client.go b/v2/internal/bridge/client.go
new file mode 100644
index 000000000..f65cffc20
--- /dev/null
+++ b/v2/internal/bridge/client.go
@@ -0,0 +1,141 @@
+package bridge
+
+import (
+ "github.com/wailsapp/wails/v2/pkg/runtime"
+)
+
+type BridgeClient struct {
+ session *session
+
+ // Tray menu cache to send to reconnecting clients
+ messageCache chan string
+}
+
+func (b BridgeClient) DeleteTrayMenuByID(id string) {
+ b.session.sendMessage("TD" + id)
+}
+
+func NewBridgeClient() *BridgeClient {
+ return &BridgeClient{
+ messageCache: make(chan string, 100),
+ }
+}
+
+func (b BridgeClient) Quit() {
+ b.session.log.Info("Quit unsupported in Bridge mode")
+}
+
+func (b BridgeClient) NotifyEvent(message string) {
+ b.session.sendMessage("n" + message)
+ b.session.log.Info("Notify: %s", message)
+}
+
+func (b BridgeClient) CallResult(message string) {
+ b.session.sendMessage("c" + message)
+}
+
+func (b BridgeClient) OpenFileDialog(dialogOptions runtime.OpenDialogOptions, callbackID string) {
+ // Handled by dialog_client
+}
+
+func (b BridgeClient) OpenMultipleFilesDialog(dialogOptions runtime.OpenDialogOptions, callbackID string) {
+ // Handled by dialog_client
+}
+
+func (b BridgeClient) OpenDirectoryDialog(dialogOptions runtime.OpenDialogOptions, callbackID string) {
+ // Handled by dialog_client
+}
+
+func (b BridgeClient) SaveDialog(dialogOptions runtime.SaveDialogOptions, callbackID string) {
+ // Handled by dialog_client
+}
+
+func (b BridgeClient) MessageDialog(dialogOptions runtime.MessageDialogOptions, callbackID string) {
+ // Handled by dialog_client
+}
+
+func (b BridgeClient) WindowSetTitle(title string) {
+ b.session.log.Info("WindowSetTitle unsupported in Bridge mode")
+}
+
+func (b BridgeClient) WindowShow() {
+ b.session.log.Info("WindowShow unsupported in Bridge mode")
+}
+
+func (b BridgeClient) WindowHide() {
+ b.session.log.Info("WindowHide unsupported in Bridge mode")
+}
+
+func (b BridgeClient) WindowCenter() {
+ b.session.log.Info("WindowCenter unsupported in Bridge mode")
+}
+
+func (b BridgeClient) WindowMaximise() {
+ b.session.log.Info("WindowMaximise unsupported in Bridge mode")
+}
+
+func (b BridgeClient) WindowUnmaximise() {
+ b.session.log.Info("WindowUnmaximise unsupported in Bridge mode")
+}
+
+func (b BridgeClient) WindowMinimise() {
+ b.session.log.Info("WindowMinimise unsupported in Bridge mode")
+}
+
+func (b BridgeClient) WindowUnminimise() {
+ b.session.log.Info("WindowUnminimise unsupported in Bridge mode")
+}
+
+func (b BridgeClient) WindowPosition(x int, y int) {
+ b.session.log.Info("WindowPosition unsupported in Bridge mode")
+}
+
+func (b BridgeClient) WindowSize(width int, height int) {
+ b.session.log.Info("WindowSize unsupported in Bridge mode")
+}
+
+func (b BridgeClient) WindowSetMinSize(width int, height int) {
+ b.session.log.Info("WindowSetMinSize unsupported in Bridge mode")
+}
+
+func (b BridgeClient) WindowSetMaxSize(width int, height int) {
+ b.session.log.Info("WindowSetMaxSize unsupported in Bridge mode")
+}
+
+func (b BridgeClient) WindowFullscreen() {
+ b.session.log.Info("WindowFullscreen unsupported in Bridge mode")
+}
+
+func (b BridgeClient) WindowUnFullscreen() {
+ b.session.log.Info("WindowUnFullscreen unsupported in Bridge mode")
+}
+
+func (b BridgeClient) WindowSetColour(colour int) {
+ b.session.log.Info("WindowSetColour unsupported in Bridge mode")
+}
+
+func (b BridgeClient) DarkModeEnabled(callbackID string) {
+ b.session.log.Info("DarkModeEnabled unsupported in Bridge mode")
+}
+
+func (b BridgeClient) MenuSetApplicationMenu(menuJSON string) {
+ b.session.log.Info("MenuSetApplicationMenu unsupported in Bridge mode")
+}
+
+func (b BridgeClient) SetTrayMenu(trayMenuJSON string) {
+ b.session.sendMessage("TS" + trayMenuJSON)
+}
+
+func (b BridgeClient) UpdateTrayMenuLabel(trayMenuJSON string) {
+ b.session.sendMessage("TU" + trayMenuJSON)
+}
+
+func (b BridgeClient) UpdateContextMenu(contextMenuJSON string) {
+ b.session.log.Info("UpdateContextMenu unsupported in Bridge mode")
+}
+
+func newBridgeClient(session *session) *BridgeClient {
+ return &BridgeClient{
+ session: session,
+ }
+}
diff --git a/v2/internal/bridge/darwin.js b/v2/internal/bridge/darwin.js
new file mode 100644
index 000000000..4758b4e29
--- /dev/null
+++ b/v2/internal/bridge/darwin.js
@@ -0,0 +1 @@
+var Wails=function(n){var t={};function e(r){if(t[r])return t[r].exports;var i=t[r]={i:r,l:!1,exports:{}};return n[r].call(i.exports,i,i.exports,e),i.l=!0,i.exports}return e.m=n,e.c=t,e.d=function(n,t,r){e.o(n,t)||Object.defineProperty(n,t,{enumerable:!0,get:r})},e.r=function(n){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(n,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(n,"__esModule",{value:!0})},e.t=function(n,t){if(1&t&&(n=e(n)),8&t)return n;if(4&t&&"object"==typeof n&&n&&n.__esModule)return n;var r=Object.create(null);if(e.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:n}),2&t&&"string"!=typeof n)for(var i in n)e.d(r,i,function(t){return n[t]}.bind(null,i));return r},e.n=function(n){var t=n&&n.__esModule?function(){return n.default}:function(){return n};return e.d(t,"a",t),t},e.o=function(n,t){return Object.prototype.hasOwnProperty.call(n,t)},e.p="",e(e.s=0)}([function(n,t,e){"use strict";e.r(t);var r={};e.r(r),e.d(r,"Trace",(function(){return v})),e.d(r,"Print",(function(){return p})),e.d(r,"Debug",(function(){return y})),e.d(r,"Info",(function(){return m})),e.d(r,"Warning",(function(){return b})),e.d(r,"Error",(function(){return g})),e.d(r,"Fatal",(function(){return h})),e.d(r,"SetLogLevel",(function(){return S})),e.d(r,"Level",(function(){return E}));var i={};e.r(i),e.d(i,"Open",(function(){return x}));var o={};e.r(o),e.d(o,"Center",(function(){return N})),e.d(o,"SetTitle",(function(){return T})),e.d(o,"Fullscreen",(function(){return j})),e.d(o,"UnFullscreen",(function(){return D})),e.d(o,"SetSize",(function(){return I})),e.d(o,"SetPosition",(function(){return P})),e.d(o,"Hide",(function(){return A})),e.d(o,"Show",(function(){return J})),e.d(o,"Maximise",(function(){return L})),e.d(o,"Unmaximise",(function(){return R})),e.d(o,"Minimise",(function(){return _})),e.d(o,"Unminimise",(function(){return F})),e.d(o,"Close",(function(){return U}));var a={};e.r(a),e.d(a,"Open",(function(){return B})),e.d(a,"Save",(function(){return H})),e.d(a,"Message",(function(){return G}));var u={};e.r(u),e.d(u,"New",(function(){return en}));var c={};e.r(c),e.d(c,"SetIcon",(function(){return rn}));var l={AppType:"desktop",Platform:function(){return"darwin"}};var s=[];function f(n){s.push(n)}function d(n){if(function(n){window.wailsInvoke(n)}(n),s.length>0)for(var t=0;t0)var a=setTimeout((function(){i(Error("Call to "+n+" timed out. Request ID: "+o))}),e);k[o]={timeoutHandle:a,reject:i,resolve:r};try{var u={name:n,args:t,callbackID:o};d("C"+JSON.stringify(u))}catch(n){console.error(n)}}))}function W(n){var t;try{t=JSON.parse(n)}catch(t){var e="Invalid JSON passed to callback: ".concat(t.message,". Message: ").concat(n);throw y(e),new Error(e)}var r=t.callbackid,i=k[r];if(!i){var o="Callback '".concat(r,"' not registered!!!");throw console.error(o),new Error(o)}clearTimeout(i.timeoutHandle),delete k[r],t.error?i.reject(t.error):i.resolve(t.result)}function M(n){var t=[].slice.apply(arguments).slice(1);return C(".wails."+n,t)}function x(n){return d("RBO"+n)}function N(){d("Wc")}function T(n){d("WT"+n)}function j(){d("WF")}function D(){d("Wf")}function I(n,t){d("Ws:"+n+":"+t)}function P(n,t){d("Wp:"+n+":"+t)}function A(){d("WH")}function J(){d("WS")}function L(){d("WM")}function R(){d("WU")}function _(){d("Wm")}function F(){d("Wu")}function U(){d("WC")}function B(n){return M("Dialog.Open",n)}function H(n){return M("Dialog.Save",n)}function G(n){return M("Dialog.Message",n)}O=window.crypto?function(){var n=new Uint32Array(1);return window.crypto.getRandomValues(n)[0]}:function(){return 9007199254740991*Math.random()},window.backend={};var q=function n(t,e){!function(n,t){if(!(n instanceof t))throw new TypeError("Cannot call a class as a function")}(this,n),e=e||-1,this.Callback=function(n){return t.apply(null,n),-1!==e&&0===(e-=1)}},z={};function V(n,t,e){z[n]=z[n]||[];var r=new q(t,e);console.log("Pushing event listener: "+n),z[n].push(r)}function K(n,t){V(n,t)}function Q(n,t){V(n,t,1)}function X(n){var t=n.name;if(z[t]){for(var e=z[t].slice(),r=0;r0)for(var t=0;t0)var a=setTimeout((function(){i(Error("Call to "+n+" timed out. Request ID: "+o))}),e);k[o]={timeoutHandle:a,reject:i,resolve:r};try{var u={name:n,args:t,callbackID:o};d("C"+JSON.stringify(u))}catch(n){console.error(n)}}))}function W(n){var t;try{t=JSON.parse(n)}catch(t){var e="Invalid JSON passed to callback: ".concat(t.message,". Message: ").concat(n);throw y(e),new Error(e)}var r=t.callbackid,i=k[r];if(!i){var o="Callback '".concat(r,"' not registered!!!");throw console.error(o),new Error(o)}clearTimeout(i.timeoutHandle),delete k[r],t.error?i.reject(t.error):i.resolve(t.result)}function x(n){var t=[].slice.apply(arguments).slice(1);return C(".wails."+n,t)}function M(n){return d("RBO"+n)}function N(){d("Wc")}function T(n){d("WT"+n)}function j(){d("WF")}function D(){d("Wf")}function I(n,t){d("Ws:"+n+":"+t)}function P(n,t){d("Wp:"+n+":"+t)}function A(){d("WH")}function J(){d("WS")}function L(){d("WM")}function R(){d("WU")}function _(){d("Wm")}function F(){d("Wu")}function U(){d("WC")}function B(n){return x("Dialog.Open",n)}function H(n){return x("Dialog.Save",n)}function G(n){return x("Dialog.Message",n)}O=window.crypto?function(){var n=new Uint32Array(1);return window.crypto.getRandomValues(n)[0]}:function(){return 9007199254740991*Math.random()},window.backend={};var q=function n(t,e){!function(n,t){if(!(n instanceof t))throw new TypeError("Cannot call a class as a function")}(this,n),e=e||-1,this.Callback=function(n){return t.apply(null,n),-1!==e&&0===(e-=1)}},z={};function V(n,t,e){z[n]=z[n]||[];var r=new q(t,e);console.log("Pushing event listener: "+n),z[n].push(r)}function K(n,t){V(n,t)}function Q(n,t){V(n,t,1)}function X(n){var t=n.name;if(z[t]){for(var e=z[t].slice(),r=0;r:.
+func (s *session) Identifier() string {
+ if s.conn != nil {
+ return s.conn.RemoteAddr().String()
+ }
+ return ""
+}
+
+func (s *session) sendMessage(msg string) error {
+ if !s.done {
+ s.writeChan <- []byte(msg)
+ }
+ return nil
+}
+
+func (s *session) start(firstSession bool) {
+ s.log.SetLogLevel(1)
+ s.log.Info("Connected to frontend.")
+ go s.writePump()
+
+ var wailsRuntime string
+ switch runtime.GOOS {
+ case "darwin":
+ wailsRuntime = darwinRuntime
+ case "windows":
+ wailsRuntime = windowsRuntime
+ case "linux":
+ wailsRuntime = linuxRuntime
+ default:
+ log.Fatal("platform not supported")
+ }
+
+ bindingsMessage := "window.wailsbindings = `" + s.bindings + "`;"
+ s.log.Info(bindingsMessage)
+ bootstrapMessage := bindingsMessage + wailsRuntime
+
+ err := s.sendMessage("b" + bootstrapMessage)
+ if err != nil {
+ s.log.Error(err.Error())
+ }
+
+ // Send menus
+ traymenus, err := s.menumanager.GetTrayMenus()
+ if err != nil {
+ s.log.Error(err.Error())
+ }
+
+ for _, trayMenu := range traymenus {
+ err := s.sendMessage("TS" + trayMenu)
+ if err != nil {
+ s.log.Error(err.Error())
+ }
+ }
+
+ for {
+ messageType, buffer, err := s.conn.ReadMessage()
+ if messageType == -1 {
+ return
+ }
+ if err != nil {
+ s.log.Error("Error reading message: %v", err)
+ err = s.conn.Close()
+ return
+ }
+
+ message := string(buffer)
+
+ s.log.Debug("Got message: %#v\n", message)
+
+ // Dispatch message as normal
+ s.client.DispatchMessage(message)
+
+ if s.done {
+ break
+ }
+ }
+}
+
+// Shutdown
+func (s *session) Shutdown() {
+ err := s.conn.Close()
+ if err != nil {
+ s.log.Error(err.Error())
+ }
+ s.done = true
+ s.log.Info("session %v exit", s.Identifier())
+}
+
+// writePump pulls messages from the writeChan and sends them to the client
+// since it uses a channel to read the messages the socket is protected without locks
+func (s *session) writePump() {
+ s.log.Debug("Session %v - writePump start", s.Identifier())
+ defer s.log.Debug("Session %v - writePump shutdown", s.Identifier())
+ for {
+ select {
+ case <-s.ctx.Done():
+ s.Shutdown()
+ return
+ case msg, ok := <-s.writeChan:
+ err := s.conn.SetWriteDeadline(time.Now().Add(1 * time.Second))
+ if err != nil {
+ s.log.Error(err.Error())
+ }
+ if !ok {
+ s.log.Debug("writeChan was closed!")
+ err := s.conn.WriteMessage(websocket.CloseMessage, []byte{})
+ if err != nil {
+ s.log.Error(err.Error())
+ }
+ return
+ }
+
+ if err := s.conn.WriteMessage(websocket.TextMessage, msg); err != nil {
+ s.log.Debug(err.Error())
+ return
+ }
+ }
+ }
+}
diff --git a/v2/internal/bridge/windows.js b/v2/internal/bridge/windows.js
new file mode 100644
index 000000000..281f47bf1
--- /dev/null
+++ b/v2/internal/bridge/windows.js
@@ -0,0 +1 @@
+var Wails=function(n){var t={};function e(r){if(t[r])return t[r].exports;var i=t[r]={i:r,l:!1,exports:{}};return n[r].call(i.exports,i,i.exports,e),i.l=!0,i.exports}return e.m=n,e.c=t,e.d=function(n,t,r){e.o(n,t)||Object.defineProperty(n,t,{enumerable:!0,get:r})},e.r=function(n){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(n,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(n,"__esModule",{value:!0})},e.t=function(n,t){if(1&t&&(n=e(n)),8&t)return n;if(4&t&&"object"==typeof n&&n&&n.__esModule)return n;var r=Object.create(null);if(e.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:n}),2&t&&"string"!=typeof n)for(var i in n)e.d(r,i,function(t){return n[t]}.bind(null,i));return r},e.n=function(n){var t=n&&n.__esModule?function(){return n.default}:function(){return n};return e.d(t,"a",t),t},e.o=function(n,t){return Object.prototype.hasOwnProperty.call(n,t)},e.p="",e(e.s=0)}([function(n,t,e){"use strict";e.r(t);var r={};e.r(r),e.d(r,"Trace",(function(){return v})),e.d(r,"Print",(function(){return p})),e.d(r,"Debug",(function(){return y})),e.d(r,"Info",(function(){return m})),e.d(r,"Warning",(function(){return b})),e.d(r,"Error",(function(){return g})),e.d(r,"Fatal",(function(){return h})),e.d(r,"SetLogLevel",(function(){return S})),e.d(r,"Level",(function(){return E}));var i={};e.r(i),e.d(i,"Open",(function(){return T}));var o={};e.r(o),e.d(o,"Center",(function(){return j})),e.d(o,"SetTitle",(function(){return x})),e.d(o,"Fullscreen",(function(){return M})),e.d(o,"UnFullscreen",(function(){return I})),e.d(o,"SetSize",(function(){return D})),e.d(o,"SetPosition",(function(){return P})),e.d(o,"Hide",(function(){return A})),e.d(o,"Show",(function(){return J})),e.d(o,"Maximise",(function(){return L})),e.d(o,"Unmaximise",(function(){return R})),e.d(o,"Minimise",(function(){return _})),e.d(o,"Unminimise",(function(){return F})),e.d(o,"Close",(function(){return U}));var a={};e.r(a),e.d(a,"Open",(function(){return B})),e.d(a,"Save",(function(){return H})),e.d(a,"Message",(function(){return G}));var u={};e.r(u),e.d(u,"New",(function(){return en}));var c={};e.r(c),e.d(c,"SetIcon",(function(){return rn}));var l={AppType:"desktop",Platform:function(){return"windows"}};var s=[];function f(n){s.push(n)}function d(n){if(function(n){window.wailsInvoke(n)}(n),s.length>0)for(var t=0;t0)var a=setTimeout((function(){i(Error("Call to "+n+" timed out. Request ID: "+o))}),e);k[o]={timeoutHandle:a,reject:i,resolve:r};try{var u={name:n,args:t,callbackID:o};d("C"+JSON.stringify(u))}catch(n){console.error(n)}}))}function W(n){var t;try{t=JSON.parse(n)}catch(t){var e="Invalid JSON passed to callback: ".concat(t.message,". Message: ").concat(n);throw y(e),new Error(e)}var r=t.callbackid,i=k[r];if(!i){var o="Callback '".concat(r,"' not registered!!!");throw console.error(o),new Error(o)}clearTimeout(i.timeoutHandle),delete k[r],t.error?i.reject(t.error):i.resolve(t.result)}function N(n){var t=[].slice.apply(arguments).slice(1);return C(".wails."+n,t)}function T(n){return d("RBO"+n)}function j(){d("Wc")}function x(n){d("WT"+n)}function M(){d("WF")}function I(){d("Wf")}function D(n,t){d("Ws:"+n+":"+t)}function P(n,t){d("Wp:"+n+":"+t)}function A(){d("WH")}function J(){d("WS")}function L(){d("WM")}function R(){d("WU")}function _(){d("Wm")}function F(){d("Wu")}function U(){d("WC")}function B(n){return N("Dialog.Open",n)}function H(n){return N("Dialog.Save",n)}function G(n){return N("Dialog.Message",n)}O=window.crypto?function(){var n=new Uint32Array(1);return window.crypto.getRandomValues(n)[0]}:function(){return 9007199254740991*Math.random()},window.backend={};var q=function n(t,e){!function(n,t){if(!(n instanceof t))throw new TypeError("Cannot call a class as a function")}(this,n),e=e||-1,this.Callback=function(n){return t.apply(null,n),-1!==e&&0===(e-=1)}},z={};function V(n,t,e){z[n]=z[n]||[];var r=new q(t,e);console.log("Pushing event listener: "+n),z[n].push(r)}function K(n,t){V(n,t)}function Q(n,t){V(n,t,1)}function X(n){var t=n.name;if(z[t]){for(var e=z[t].slice(),r=0;rdata);
+ return -1;
+}
+
+const char* getJSONString(JsonNode *item, const char* key) {
+ // Get key
+ JsonNode *node = json_find_member(item, key);
+ const char *result = "";
+ if ( node != NULL && node->tag == JSON_STRING) {
+ result = node->string_;
+ }
+ return result;
+}
+
+void ABORT_JSON(JsonNode *node, const char* key) {
+ ABORT("Unable to read required key '%s' from JSON: %s\n", key, json_encode(node));
+}
+
+const char* mustJSONString(JsonNode *node, const char* key) {
+ const char* result = getJSONString(node, key);
+ if ( result == NULL ) {
+ ABORT_JSON(node, key);
+ }
+ return result;
+}
+JsonNode* mustJSONObject(JsonNode *node, const char* key) {
+ struct JsonNode* result = getJSONObject(node, key);
+ if ( result == NULL ) {
+ ABORT_JSON(node, key);
+ }
+ return result;
+}
+
+JsonNode* getJSONObject(JsonNode* node, const char* key) {
+ return json_find_member(node, key);
+}
+
+bool getJSONBool(JsonNode *item, const char* key, bool *result) {
+ JsonNode *node = json_find_member(item, key);
+ if ( node != NULL && node->tag == JSON_BOOL) {
+ *result = node->bool_;
+ return true;
+ }
+ return false;
+}
+
+bool getJSONInt(JsonNode *item, const char* key, int *result) {
+ JsonNode *node = json_find_member(item, key);
+ if ( node != NULL && node->tag == JSON_NUMBER) {
+ *result = (int) node->number_;
+ return true;
+ }
+ return false;
+}
+
+JsonNode* mustParseJSON(const char* JSON) {
+ JsonNode* parsedUpdate = json_decode(JSON);
+ if ( parsedUpdate == NULL ) {
+ ABORT("Unable to decode JSON: %s\n", JSON);
+ }
+ return parsedUpdate;
+}
\ No newline at end of file
diff --git a/v2/internal/ffenestri/common.h b/v2/internal/ffenestri/common.h
new file mode 100644
index 000000000..7f6e3a509
--- /dev/null
+++ b/v2/internal/ffenestri/common.h
@@ -0,0 +1,36 @@
+//
+// Created by Lea Anthony on 6/1/21.
+//
+
+#ifndef COMMON_H
+#define COMMON_H
+
+#include
+#include
+#include "string.h"
+#include "hashmap.h"
+#include "vec.h"
+#include "json.h"
+
+#define STREQ(a,b) strcmp(a, b) == 0
+#define STREMPTY(string) strlen(string) == 0
+#define STRCOPY(a) concat(a, "")
+#define STR_HAS_CHARS(input) input != NULL && strlen(input) > 0
+#define MEMFREE(input) free((void*)input); input = NULL;
+#define FREE_AND_SET(variable, value) if( variable != NULL ) { MEMFREE(variable); } variable = value
+
+// Credit: https://stackoverflow.com/a/8465083
+char* concat(const char *string1, const char *string2);
+void ABORT(const char *message, ...);
+int freeHashmapItem(void *const context, struct hashmap_element_s *const e);
+const char* getJSONString(JsonNode *item, const char* key);
+const char* mustJSONString(JsonNode *node, const char* key);
+JsonNode* getJSONObject(JsonNode* node, const char* key);
+JsonNode* mustJSONObject(JsonNode *node, const char* key);
+
+bool getJSONBool(JsonNode *item, const char* key, bool *result);
+bool getJSONInt(JsonNode *item, const char* key, int *result);
+
+JsonNode* mustParseJSON(const char* JSON);
+
+#endif //ASSETS_C_COMMON_H
diff --git a/v2/internal/ffenestri/contextmenus_darwin.c b/v2/internal/ffenestri/contextmenus_darwin.c
new file mode 100644
index 000000000..fb2eb4105
--- /dev/null
+++ b/v2/internal/ffenestri/contextmenus_darwin.c
@@ -0,0 +1,99 @@
+////
+//// Created by Lea Anthony on 6/1/21.
+////
+//
+
+#include "ffenestri_darwin.h"
+#include "common.h"
+#include "contextmenus_darwin.h"
+#include "menu_darwin.h"
+
+ContextMenu* NewContextMenu(const char* contextMenuJSON) {
+ ContextMenu* result = malloc(sizeof(ContextMenu));
+
+ JsonNode* processedJSON = json_decode(contextMenuJSON);
+ if( processedJSON == NULL ) {
+ ABORT("[NewTrayMenu] Unable to parse TrayMenu JSON: %s", contextMenuJSON);
+ }
+ // Save reference to this json
+ result->processedJSON = processedJSON;
+
+ result->ID = mustJSONString(processedJSON, "ID");
+ JsonNode* processedMenu = mustJSONObject(processedJSON, "ProcessedMenu");
+
+ result->menu = NewMenu(processedMenu);
+ result->nsmenu = NULL;
+ result->menu->menuType = ContextMenuType;
+ result->menu->parentData = result;
+ result->contextMenuData = NULL;
+ return result;
+}
+
+ContextMenu* GetContextMenuByID(ContextMenuStore* store, const char *contextMenuID) {
+ return (ContextMenu*)hashmap_get(&store->contextMenuMap, (char*)contextMenuID, strlen(contextMenuID));
+}
+
+void DeleteContextMenu(ContextMenu* contextMenu) {
+ // Free Menu
+ DeleteMenu(contextMenu->menu);
+
+ // Delete any context menu data we may have stored
+ if( contextMenu->contextMenuData != NULL ) {
+ MEMFREE(contextMenu->contextMenuData);
+ }
+
+ // Free JSON
+ if (contextMenu->processedJSON != NULL ) {
+ json_delete(contextMenu->processedJSON);
+ contextMenu->processedJSON = NULL;
+ }
+
+ // Free context menu
+ free(contextMenu);
+}
+
+int freeContextMenu(void *const context, struct hashmap_element_s *const e) {
+ DeleteContextMenu(e->data);
+ return -1;
+}
+
+void ShowContextMenu(ContextMenuStore* store, id mainWindow, const char *contextMenuID, const char *contextMenuData) {
+
+ // If no context menu ID was given, abort
+ if( contextMenuID == NULL ) {
+ return;
+ }
+
+ ContextMenu* contextMenu = GetContextMenuByID(store, contextMenuID);
+
+ // We don't need the ID now
+ MEMFREE(contextMenuID);
+
+ if( contextMenu == NULL ) {
+ // Free context menu data
+ if( contextMenuData != NULL ) {
+ MEMFREE(contextMenuData);
+ return;
+ }
+ }
+
+ // We need to store the context menu data. Free existing data if we have it
+ // and set to the new value.
+ FREE_AND_SET(contextMenu->contextMenuData, contextMenuData);
+
+ // Grab the content view and show the menu
+ id contentView = msg_reg(mainWindow, s("contentView"));
+
+ // Get the triggering event
+ id menuEvent = msg_reg(mainWindow, s("currentEvent"));
+
+ if( contextMenu->nsmenu == NULL ) {
+ // GetMenu creates the NSMenu
+ contextMenu->nsmenu = GetMenu(contextMenu->menu);
+ }
+
+ // Show popup
+ ((id(*)(id, SEL, id, id, id))objc_msgSend)(c("NSMenu"), s("popUpContextMenu:withEvent:forView:"), contextMenu->nsmenu, menuEvent, contentView);
+
+}
+
diff --git a/v2/internal/ffenestri/contextmenus_darwin.h b/v2/internal/ffenestri/contextmenus_darwin.h
new file mode 100644
index 000000000..a1e7b976a
--- /dev/null
+++ b/v2/internal/ffenestri/contextmenus_darwin.h
@@ -0,0 +1,33 @@
+////
+//// Created by Lea Anthony on 6/1/21.
+////
+//
+#ifndef CONTEXTMENU_DARWIN_H
+#define CONTEXTMENU_DARWIN_H
+
+#include "json.h"
+#include "menu_darwin.h"
+#include "contextmenustore_darwin.h"
+
+typedef struct {
+ const char* ID;
+ id nsmenu;
+ Menu* menu;
+
+ JsonNode* processedJSON;
+
+ // Context menu data is given by the frontend when clicking a context menu.
+ // We send this to the backend when an item is selected
+ const char* contextMenuData;
+} ContextMenu;
+
+
+ContextMenu* NewContextMenu(const char* contextMenuJSON);
+
+ContextMenu* GetContextMenuByID( ContextMenuStore* store, const char *contextMenuID);
+void DeleteContextMenu(ContextMenu* contextMenu);
+int freeContextMenu(void *const context, struct hashmap_element_s *const e);
+
+void ShowContextMenu(ContextMenuStore* store, id mainWindow, const char *contextMenuID, const char *contextMenuData);
+
+#endif //CONTEXTMENU_DARWIN_H
diff --git a/v2/internal/ffenestri/contextmenustore_darwin.c b/v2/internal/ffenestri/contextmenustore_darwin.c
new file mode 100644
index 000000000..c777f014e
--- /dev/null
+++ b/v2/internal/ffenestri/contextmenustore_darwin.c
@@ -0,0 +1,65 @@
+
+#include "contextmenus_darwin.h"
+#include "contextmenustore_darwin.h"
+
+ContextMenuStore* NewContextMenuStore() {
+
+ ContextMenuStore* result = malloc(sizeof(ContextMenuStore));
+
+ // Allocate Context Menu Store
+ if( 0 != hashmap_create((const unsigned)4, &result->contextMenuMap)) {
+ ABORT("[NewContextMenus] Not enough memory to allocate contextMenuStore!");
+ }
+
+ return result;
+}
+
+void AddContextMenuToStore(ContextMenuStore* store, const char* contextMenuJSON) {
+ ContextMenu* newMenu = NewContextMenu(contextMenuJSON);
+
+ //TODO: check if there is already an entry for this menu
+ hashmap_put(&store->contextMenuMap, newMenu->ID, strlen(newMenu->ID), newMenu);
+}
+
+ContextMenu* GetContextMenuFromStore(ContextMenuStore* store, const char* menuID) {
+ // Get the current menu
+ return hashmap_get(&store->contextMenuMap, menuID, strlen(menuID));
+}
+
+void UpdateContextMenuInStore(ContextMenuStore* store, const char* menuJSON) {
+ ContextMenu* newContextMenu = NewContextMenu(menuJSON);
+
+ // Get the current menu
+ ContextMenu *currentMenu = GetContextMenuFromStore(store, newContextMenu->ID);
+ if ( currentMenu == NULL ) {
+ ABORT("Attempted to update unknown context menu with ID '%s'.", newContextMenu->ID);
+ }
+
+ hashmap_remove(&store->contextMenuMap, newContextMenu->ID, strlen(newContextMenu->ID));
+
+ // Save the status bar reference
+ DeleteContextMenu(currentMenu);
+
+ hashmap_put(&store->contextMenuMap, newContextMenu->ID, strlen(newContextMenu->ID), newContextMenu);
+
+}
+
+
+void DeleteContextMenuStore(ContextMenuStore* store) {
+
+ // Guard against NULLs
+ if( store == NULL ) {
+ return;
+ }
+
+ // Delete context menus
+ if( hashmap_num_entries(&store->contextMenuMap) > 0 ) {
+ if (0 != hashmap_iterate_pairs(&store->contextMenuMap, freeContextMenu, NULL)) {
+ ABORT("[DeleteContextMenuStore] Failed to release contextMenuStore entries!");
+ }
+ }
+
+ // Free context menu hashmap
+ hashmap_destroy(&store->contextMenuMap);
+
+}
diff --git a/v2/internal/ffenestri/contextmenustore_darwin.h b/v2/internal/ffenestri/contextmenustore_darwin.h
new file mode 100644
index 000000000..793eef691
--- /dev/null
+++ b/v2/internal/ffenestri/contextmenustore_darwin.h
@@ -0,0 +1,27 @@
+//
+// Created by Lea Anthony on 7/1/21.
+//
+
+#ifndef CONTEXTMENUSTORE_DARWIN_H
+#define CONTEXTMENUSTORE_DARWIN_H
+
+#include "common.h"
+
+typedef struct {
+
+ int dummy;
+
+ // This is our context menu store which keeps track
+ // of all instances of ContextMenus
+ struct hashmap_s contextMenuMap;
+
+} ContextMenuStore;
+
+ContextMenuStore* NewContextMenuStore();
+
+void DeleteContextMenuStore(ContextMenuStore* store);
+void UpdateContextMenuInStore(ContextMenuStore* store, const char* menuJSON);
+
+void AddContextMenuToStore(ContextMenuStore* store, const char* contextMenuJSON);
+
+#endif //CONTEXTMENUSTORE_DARWIN_H
diff --git a/v2/internal/ffenestri/defaultdialogicons_darwin.c b/v2/internal/ffenestri/defaultdialogicons_darwin.c
new file mode 100644
index 000000000..0c79a6b55
--- /dev/null
+++ b/v2/internal/ffenestri/defaultdialogicons_darwin.c
@@ -0,0 +1,41 @@
+// defaultdialogicons_darwin.c
+// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL.
+// This file was auto-generated. DO NOT MODIFY.
+
+const unsigned char defaultDialogIcon0Name[] = { 0x69, 0x6e, 0x66, 0x6f, 0x2d, 0x64, 0x61, 0x72, 0x6b, 0x00 };
+const unsigned char defaultDialogIcon0Length[] = { 0x37, 0x38, 0x30, 0x00 };
+const unsigned char defaultDialogIcon0Data[] = { 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x40, 0x0, 0x0, 0x0, 0x40, 0x8, 0x3, 0x0, 0x0, 0x0, 0x9d, 0xb7, 0x81, 0xec, 0x0, 0x0, 0x0, 0x84, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x20, 0xdb, 0xe6, 0xd1, 0x0, 0x0, 0x0, 0x2b, 0x74, 0x52, 0x4e, 0x53, 0x0, 0xf9, 0x9c, 0xb1, 0xe7, 0x4b, 0x91, 0x3a, 0x1b, 0xe3, 0x1e, 0xa, 0xae, 0x51, 0xe0, 0x98, 0x32, 0x4, 0x66, 0x6d, 0x2b, 0x63, 0x5d, 0x18, 0x11, 0xd6, 0xd0, 0xc8, 0xc2, 0x40, 0x7, 0x76, 0x16, 0x48, 0xa0, 0x2f, 0x57, 0xf1, 0xf0, 0x85, 0x77, 0x2c, 0xf, 0x6d, 0x84, 0xfd, 0x3d, 0x0, 0x0, 0x2, 0xc, 0x49, 0x44, 0x41, 0x54, 0x58, 0xc3, 0xed, 0x57, 0xd9, 0x96, 0x82, 0x30, 0xc, 0x15, 0x2c, 0x4b, 0x91, 0x5d, 0x40, 0x10, 0x5, 0xf7, 0x65, 0xfc, 0xff, 0xff, 0x9b, 0x63, 0xca, 0xa1, 0x40, 0xb, 0x61, 0xa6, 0xc7, 0x37, 0xf3, 0x18, 0x92, 0xdb, 0x66, 0xb9, 0x69, 0x58, 0x7c, 0xe5, 0xb3, 0x62, 0x87, 0x46, 0xfa, 0x78, 0xa4, 0x46, 0x68, 0xff, 0xc3, 0x79, 0xe3, 0x99, 0x25, 0xd5, 0x5e, 0x20, 0x1a, 0x2d, 0x4d, 0x6f, 0xf3, 0x27, 0x77, 0x2b, 0xf0, 0x5f, 0x3, 0xf1, 0x3, 0x6b, 0xb6, 0xfb, 0x7e, 0xa9, 0xbd, 0x24, 0xa2, 0x2d, 0xf7, 0xb3, 0xdc, 0x1d, 0x1d, 0xdc, 0xa5, 0x10, 0xba, 0x83, 0xfb, 0x1b, 0x7e, 0xd7, 0x83, 0x14, 0x5, 0xe9, 0xe2, 0xf9, 0x6, 0xe6, 0xbf, 0x6e, 0xcd, 0xa9, 0x1b, 0x5b, 0x89, 0x93, 0xe7, 0x4e, 0x62, 0xc5, 0x2e, 0x6d, 0x21, 0xd7, 0x93, 0xee, 0x2b, 0xb3, 0x8d, 0xd7, 0xb3, 0x7b, 0x15, 0xf5, 0xda, 0xbc, 0x98, 0xab, 0x9, 0x7f, 0xb7, 0x31, 0xda, 0x1d, 0x25, 0xb1, 0xed, 0x9a, 0x8f, 0xee, 0x38, 0x42, 0x73, 0x3e, 0xc9, 0x2a, 0xd9, 0xd7, 0x2a, 0x23, 0xcd, 0x1d, 0x46, 0xe3, 0x67, 0xdf, 0xb7, 0xe1, 0x98, 0x41, 0xb8, 0x65, 0x16, 0x23, 0x79, 0x30, 0x58, 0x94, 0xcb, 0xcd, 0x44, 0x7f, 0x2e, 0x59, 0x86, 0xc, 0x69, 0xfd, 0x29, 0xf3, 0x5f, 0x4d, 0x66, 0x99, 0x21, 0x50, 0x59, 0x3f, 0xe8, 0xec, 0xfe, 0x83, 0xf3, 0x9f, 0xcf, 0x1, 0xc1, 0x58, 0x14, 0xba, 0xa4, 0x7f, 0x21, 0x0, 0x72, 0xee, 0x1f, 0x78, 0xba, 0x5e, 0x4f, 0xfd, 0x2b, 0x9d, 0x9, 0x4, 0x21, 0x74, 0x75, 0xc4, 0xee, 0x96, 0xf5, 0xb5, 0xf1, 0x5b, 0x17, 0xf7, 0x75, 0x19, 0x8b, 0x34, 0x1a, 0xf2, 0x4f, 0x83, 0xfa, 0x57, 0x42, 0x5d, 0x85, 0xaa, 0x55, 0x3b, 0xb8, 0xc2, 0x90, 0x9b, 0x1, 0x68, 0x8f, 0xb, 0xc9, 0x69, 0x97, 0x81, 0xf2, 0x8, 0x67, 0x5, 0x7d, 0xe5, 0xc1, 0x87, 0x7b, 0x9, 0x81, 0xdd, 0x29, 0xbd, 0x47, 0x43, 0x2d, 0x44, 0xeb, 0x1f, 0x7a, 0x3a, 0xf, 0x2, 0xf3, 0xc4, 0xdc, 0x1e, 0x98, 0x1d, 0x6a, 0xc, 0xc1, 0x12, 0x7b, 0xe6, 0xac, 0x24, 0x42, 0x6a, 0xa2, 0x12, 0x58, 0x22, 0xda, 0x46, 0x96, 0x15, 0x89, 0x5a, 0xe0, 0x5c, 0x19, 0x75, 0x31, 0xa9, 0x50, 0x2f, 0x90, 0xdc, 0xd5, 0x34, 0xf7, 0x47, 0x50, 0x43, 0x75, 0xa9, 0xdd, 0x65, 0x9, 0x24, 0xd6, 0x12, 0xe9, 0x25, 0xa7, 0x8e, 0x5, 0x25, 0xb, 0xbb, 0x3c, 0x2, 0x4d, 0x22, 0x58, 0x6, 0x42, 0xc1, 0x40, 0x12, 0x38, 0xaf, 0xcb, 0xa8, 0x14, 0x72, 0xe8, 0xc8, 0xf9, 0xa1, 0x8b, 0xbc, 0x83, 0x2c, 0xa6, 0x1d, 0x4d, 0xfd, 0x56, 0x14, 0xf9, 0x5c, 0x80, 0xbc, 0x78, 0xeb, 0x6b, 0x65, 0x0, 0xe5, 0x10, 0xb0, 0x24, 0x72, 0x0, 0x3c, 0x89, 0xbc, 0x8c, 0x38, 0x0, 0x2f, 0x23, 0xd6, 0x48, 0x1c, 0x0, 0x6f, 0x24, 0xde, 0xca, 0x38, 0x0, 0x6f, 0x65, 0x84, 0x4c, 0x1c, 0x0, 0x27, 0x13, 0x67, 0x28, 0xe, 0xc0, 0x8d, 0xb1, 0x81, 0xc2, 0x1, 0xf0, 0x81, 0xc2, 0x47, 0x1a, 0xa, 0xc0, 0x47, 0x1a, 0x3a, 0x54, 0x39, 0x99, 0x90, 0xa1, 0x8a, 0x8e, 0xf5, 0x74, 0x62, 0xac, 0xe3, 0xf, 0xcb, 0xed, 0x86, 0x3c, 0x2c, 0xd8, 0xd3, 0x96, 0x24, 0xf8, 0xd3, 0xa6, 0xfe, 0xb8, 0xce, 0x7f, 0xde, 0x6d, 0xfe, 0xbc, 0xab, 0x2d, 0x18, 0xca, 0x2b, 0xe, 0xbe, 0x64, 0x19, 0xd8, 0x92, 0x85, 0xaf, 0x79, 0x17, 0xbb, 0x97, 0xe1, 0xb, 0xb2, 0xe6, 0x61, 0x8b, 0x26, 0x11, 0x17, 0x4d, 0xf5, 0x55, 0x57, 0x7d, 0xd9, 0x56, 0x5f, 0xf7, 0xd5, 0x7f, 0x38, 0xd4, 0x7f, 0x79, 0xf0, 0x9f, 0xae, 0xba, 0x86, 0x9f, 0xae, 0xaf, 0x7c, 0x54, 0x7e, 0x1, 0x7, 0x4e, 0x88, 0x96, 0x1d, 0xbb, 0xbc, 0x56, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82, 0x00 };
+const unsigned char defaultDialogIcon1Name[] = { 0x69, 0x6e, 0x66, 0x6f, 0x2d, 0x64, 0x61, 0x72, 0x6b, 0x32, 0x78, 0x00 };
+const unsigned char defaultDialogIcon1Length[] = { 0x31, 0x32, 0x39, 0x35, 0x00 };
+const unsigned char defaultDialogIcon1Data[] = { 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x80, 0x0, 0x0, 0x0, 0x80, 0x8, 0x3, 0x0, 0x0, 0x0, 0xf4, 0xe0, 0x91, 0xf9, 0x0, 0x0, 0x0, 0x96, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x25, 0xc5, 0xa8, 0x0, 0x0, 0x0, 0x31, 0x74, 0x52, 0x4e, 0x53, 0x0, 0xfb, 0x55, 0x3, 0x61, 0x95, 0xc, 0xd7, 0xb7, 0x8a, 0x82, 0x39, 0xe5, 0x40, 0x19, 0x44, 0x2b, 0x4e, 0xee, 0xc6, 0xbf, 0x48, 0x25, 0x21, 0xe2, 0xb3, 0x67, 0xe8, 0x33, 0xd0, 0x6c, 0x42, 0x9, 0xcb, 0xf, 0xf6, 0xc2, 0xbc, 0xb0, 0xa8, 0x71, 0x52, 0x14, 0x7, 0x90, 0x7c, 0x8f, 0x11, 0x7b, 0xbe, 0x95, 0xf5, 0x71, 0x0, 0x0, 0x3, 0xf7, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0xec, 0x97, 0xd9, 0x72, 0xaa, 0x40, 0x10, 0x86, 0xdb, 0xc, 0xc8, 0xe, 0xa2, 0x2c, 0xee, 0x68, 0xdc, 0xf5, 0x98, 0xd4, 0xbc, 0xff, 0xcb, 0x9d, 0x4a, 0x9d, 0x53, 0xa1, 0x41, 0x98, 0x9e, 0x19, 0x30, 0x95, 0xb, 0xbf, 0xeb, 0x6, 0x7a, 0xf9, 0x7b, 0x1, 0x5e, 0xbc, 0x78, 0xf1, 0xe2, 0x85, 0x3e, 0x9b, 0x30, 0x5b, 0x16, 0x71, 0x5c, 0x2c, 0xb3, 0x70, 0x3, 0x3f, 0xcb, 0x30, 0x5a, 0x9b, 0x7, 0x9f, 0x23, 0xfc, 0x83, 0xb9, 0x8e, 0x86, 0xf0, 0x13, 0xdc, 0x2, 0x77, 0x32, 0xe0, 0x8d, 0xc, 0x26, 0x6e, 0x70, 0x83, 0xa7, 0xc2, 0xd2, 0xd3, 0x8e, 0xb, 0xd9, 0x9d, 0x52, 0x6, 0xcf, 0x62, 0xe4, 0x2c, 0xb8, 0x4, 0xb, 0x67, 0x4, 0xcf, 0xc0, 0xb3, 0xb9, 0x34, 0xb6, 0x7, 0x7d, 0x53, 0x24, 0x5c, 0x89, 0xa4, 0xe8, 0x37, 0xf9, 0x9, 0x57, 0x26, 0xe9, 0xaf, 0x10, 0x43, 0x67, 0xc0, 0x35, 0x18, 0x38, 0x3d, 0xf5, 0x65, 0x3c, 0xe5, 0x9a, 0x4c, 0x63, 0xe8, 0xe, 0x73, 0x78, 0x7, 0x1c, 0xd6, 0x39, 0xfd, 0xb3, 0xd6, 0xc, 0xfb, 0xdb, 0xa3, 0x79, 0x37, 0x8c, 0xbb, 0x79, 0xdc, 0xfa, 0xad, 0x35, 0x9a, 0x75, 0x2c, 0x43, 0x6e, 0xf1, 0x26, 0x56, 0xae, 0x17, 0x32, 0x40, 0xb0, 0xd0, 0x73, 0x57, 0xbc, 0x9, 0x2b, 0x87, 0xe, 0x4, 0xe3, 0x86, 0xc8, 0xf7, 0xe7, 0xbc, 0xc5, 0xdb, 0xf3, 0xbe, 0x21, 0x13, 0xe3, 0x0, 0xb4, 0x99, 0x3f, 0xbe, 0xcf, 0x36, 0xae, 0x20, 0xe0, 0x6a, 0xd8, 0x8f, 0x1e, 0xcf, 0x75, 0xe5, 0x67, 0xf2, 0x3a, 0x13, 0xf, 0x48, 0xbc, 0x9, 0xaf, 0x63, 0x32, 0xad, 0xef, 0x3f, 0xc8, 0xcf, 0xba, 0x80, 0x14, 0x17, 0xeb, 0x41, 0x8a, 0x3a, 0x1e, 0xd4, 0xe3, 0x5f, 0xcc, 0x99, 0xb4, 0xef, 0xf3, 0x45, 0x3d, 0x7, 0x1a, 0xf5, 0xaf, 0x15, 0xd2, 0x1d, 0x2a, 0x75, 0xaf, 0x5b, 0x93, 0x8f, 0xb2, 0xe, 0x82, 0x41, 0x55, 0xca, 0x5, 0x28, 0x12, 0x8d, 0xab, 0x1, 0x4, 0x8a, 0xfd, 0x5f, 0x7d, 0xdc, 0xca, 0x40, 0x99, 0xcc, 0xaa, 0x86, 0x90, 0x2b, 0x65, 0xb0, 0xfa, 0xb0, 0xfd, 0xe, 0x1a, 0xbc, 0xdb, 0xd5, 0x20, 0x86, 0xda, 0xd, 0xf0, 0xc1, 0x40, 0xb, 0xf6, 0xa1, 0xdb, 0xa, 0x4e, 0xa5, 0x7a, 0x6, 0x68, 0x63, 0x54, 0x94, 0xe4, 0x80, 0x24, 0x31, 0xc7, 0x18, 0xd0, 0x1, 0x83, 0x63, 0x62, 0x49, 0x1, 0x4c, 0x2b, 0xf9, 0x87, 0x4e, 0xfc, 0xe1, 0x88, 0xe9, 0x46, 0xbd, 0x0, 0x36, 0x83, 0x4e, 0x30, 0x5b, 0xb9, 0x8, 0x23, 0x5c, 0x37, 0x4b, 0xac, 0xff, 0x4f, 0xc3, 0x34, 0x8d, 0x4f, 0x71, 0x2f, 0x58, 0x58, 0x4f, 0x23, 0xa0, 0x49, 0x70, 0xf3, 0x8a, 0xfb, 0x3f, 0xf5, 0xbf, 0x8c, 0xfc, 0x14, 0x44, 0x64, 0x78, 0xa4, 0x24, 0x40, 0x52, 0x60, 0x87, 0x23, 0x10, 0xb1, 0x1c, 0xfc, 0x37, 0x5b, 0x82, 0x88, 0x8, 0xa7, 0xb4, 0x50, 0x4a, 0x80, 0xb, 0x42, 0x56, 0xdf, 0x7, 0x12, 0x8, 0x71, 0x55, 0x52, 0xe0, 0xe1, 0xfd, 0x27, 0x9e, 0x5d, 0x61, 0x69, 0x19, 0x8a, 0xdb, 0xa, 0xef, 0x46, 0xf, 0xc4, 0xd8, 0xf2, 0x1b, 0x2c, 0x2d, 0x2d, 0x53, 0x10, 0xb2, 0xc6, 0x6d, 0x45, 0xb4, 0x0, 0xee, 0x0, 0x26, 0x6d, 0x4b, 0x88, 0x9b, 0x59, 0x1c, 0xd9, 0x4a, 0xcf, 0x80, 0xb, 0xd5, 0xe2, 0xdf, 0xf2, 0x1e, 0x33, 0xea, 0x46, 0x92, 0x9d, 0x5, 0xc, 0x55, 0x6b, 0x2, 0x14, 0x73, 0xf9, 0x6b, 0x3, 0xdd, 0x89, 0x3e, 0x23, 0xca, 0x8a, 0xd4, 0x42, 0x61, 0x4a, 0xdf, 0x5b, 0x1e, 0x97, 0x13, 0xcc, 0x9, 0x8b, 0x45, 0x82, 0x78, 0xe6, 0xfb, 0xb3, 0x18, 0x30, 0xb4, 0xb8, 0x4f, 0xd0, 0xca, 0x6d, 0x47, 0x2f, 0xc1, 0xee, 0x6b, 0x71, 0x77, 0x83, 0x36, 0x2, 0x34, 0x4, 0xaf, 0xd0, 0x2b, 0x57, 0x34, 0xe, 0x3, 0x99, 0x91, 0xb5, 0x87, 0x9e, 0xd9, 0xa3, 0x1, 0x2b, 0xa3, 0xd5, 0x33, 0xf4, 0xcc, 0x59, 0xa2, 0xbf, 0x86, 0x28, 0x4d, 0x39, 0xf4, 0x4c, 0x8e, 0xca, 0xdb, 0x36, 0xe2, 0x23, 0xf4, 0xff, 0x2d, 0x79, 0xf8, 0x7e, 0xdd, 0x3, 0x92, 0x27, 0x33, 0xfa, 0x7b, 0x8f, 0xe8, 0x91, 0xed, 0x82, 0xc, 0xd1, 0xbf, 0x7b, 0xa0, 0xf6, 0x3e, 0x5a, 0x60, 0x6b, 0x68, 0xc6, 0x24, 0xa6, 0x10, 0x71, 0xf, 0x10, 0x78, 0xf4, 0x9f, 0xe2, 0x1, 0xed, 0x57, 0xa5, 0xa4, 0x6e, 0x1, 0x43, 0x6f, 0xef, 0x3, 0x34, 0xe3, 0x97, 0x32, 0x61, 0x40, 0x13, 0xaa, 0xf9, 0xcb, 0x4a, 0x89, 0x4f, 0xa1, 0x91, 0xd, 0x5a, 0x18, 0x40, 0x40, 0xdc, 0x3, 0x44, 0x7c, 0x7c, 0x43, 0x44, 0x24, 0x97, 0xd3, 0xb7, 0xd2, 0xfe, 0xd, 0x24, 0xd8, 0x52, 0x19, 0xcb, 0x4a, 0x83, 0xe3, 0x33, 0x1c, 0x38, 0x96, 0xf6, 0x59, 0xb3, 0xa8, 0x91, 0x4c, 0x3b, 0x39, 0x40, 0x37, 0xd9, 0x92, 0x5a, 0x45, 0xf7, 0x67, 0x38, 0x70, 0xa7, 0xd6, 0x51, 0x4c, 0xec, 0x62, 0xc2, 0x1, 0x95, 0x8d, 0x1c, 0xff, 0x4e, 0x7, 0xfe, 0xb6, 0x6f, 0x6, 0x29, 0xc, 0x2, 0x41, 0x10, 0x3c, 0xc4, 0x63, 0xc4, 0x78, 0x8a, 0x10, 0x90, 0x24, 0x67, 0x21, 0xfe, 0xff, 0x75, 0x1, 0x73, 0x89, 0x18, 0x28, 0xb1, 0xc, 0xb3, 0x2b, 0x3b, 0x1f, 0xb0, 0x41, 0xdd, 0x9d, 0xe9, 0xae, 0x9, 0x7f, 0x5, 0xe1, 0x1f, 0x61, 0xf8, 0x6f, 0x18, 0x7e, 0x10, 0xc1, 0x51, 0xc, 0x2, 0xc4, 0x51, 0xcc, 0x97, 0x11, 0xb, 0x50, 0x97, 0x11, 0x5f, 0xc7, 0x2c, 0x40, 0x5d, 0xc7, 0xdc, 0x90, 0xb0, 0x0, 0xd5, 0x90, 0x70, 0x4b, 0xc6, 0x2, 0x54, 0x4b, 0xc6, 0x4d, 0x29, 0xb, 0x50, 0x4d, 0x29, 0xb7, 0xe5, 0x2c, 0x40, 0xb5, 0xe5, 0x3c, 0x98, 0xb0, 0x0, 0x35, 0x98, 0xf0, 0x68, 0xc6, 0x2, 0xd4, 0x68, 0xc6, 0xc3, 0x29, 0xb, 0x50, 0xc3, 0x29, 0x8f, 0xe7, 0x2c, 0xc0, 0x8d, 0xe7, 0x6c, 0x50, 0xb0, 0x0, 0x6f, 0x50, 0xb0, 0x45, 0xc3, 0x2, 0xbc, 0x45, 0xc3, 0x26, 0x15, 0xb, 0x60, 0x93, 0xca, 0xd8, 0x74, 0x2c, 0x80, 0x6d, 0x3a, 0x65, 0x54, 0xb2, 0x0, 0x36, 0x2a, 0xd3, 0xb6, 0x6a, 0xe3, 0xcd, 0xea, 0x4d, 0x76, 0xfd, 0xc3, 0xd9, 0xf5, 0x3e, 0xb0, 0xb8, 0x88, 0xc0, 0x42, 0x45, 0x36, 0x4d, 0x37, 0x35, 0x58, 0x8d, 0x88, 0x6c, 0x64, 0x68, 0xf5, 0xac, 0x86, 0xa1, 0x82, 0x5c, 0x6b, 0x1e, 0x5a, 0xe5, 0x10, 0xdb, 0xc5, 0x7, 0x97, 0xe1, 0xd1, 0x6d, 0x7c, 0x78, 0xbd, 0x5b, 0x7c, 0x3f, 0x40, 0x7c, 0xff, 0x67, 0x80, 0xe1, 0xb5, 0x0, 0x18, 0x42, 0x11, 0x8e, 0xdb, 0xd5, 0x41, 0x2c, 0x8d, 0x86, 0x58, 0x72, 0xc3, 0x78, 0x7e, 0x80, 0x4c, 0xfd, 0x7a, 0x90, 0xa9, 0x5f, 0x80, 0x4c, 0x39, 0xa2, 0x5c, 0x3b, 0xc2, 0x6c, 0xc3, 0x29, 0x4f, 0x9c, 0x2f, 0x1, 0xa0, 0x31, 0x1e, 0xe9, 0x44, 0xa8, 0x75, 0xac, 0xaa, 0x11, 0xa0, 0xd6, 0xdc, 0xb1, 0xde, 0x78, 0xb0, 0xd9, 0xa0, 0xdd, 0xf7, 0xa3, 0xc0, 0xed, 0x9, 0xe0, 0xfd, 0x9, 0x2c, 0x38, 0x7c, 0x56, 0x3c, 0xce, 0x6b, 0x9e, 0x7e, 0x5e, 0xae, 0x78, 0x1c, 0x65, 0xc9, 0x25, 0x81, 0x35, 0x9f, 0xef, 0x45, 0xa7, 0x6e, 0xf6, 0xc7, 0x8b, 0x45, 0x27, 0xb5, 0xea, 0x55, 0xb7, 0x6d, 0x3d, 0xad, 0x7a, 0x95, 0x2a, 0x55, 0xaa, 0x54, 0xa9, 0xcd, 0xf5, 0x6, 0xc2, 0x69, 0xab, 0xf3, 0x71, 0x7e, 0x8e, 0x8, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82, 0x00 };
+const unsigned char defaultDialogIcon2Name[] = { 0x69, 0x6e, 0x66, 0x6f, 0x2d, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x00 };
+const unsigned char defaultDialogIcon2Length[] = { 0x37, 0x36, 0x34, 0x00 };
+const unsigned char defaultDialogIcon2Data[] = { 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x40, 0x0, 0x0, 0x0, 0x40, 0x8, 0x3, 0x0, 0x0, 0x0, 0x9d, 0xb7, 0x81, 0xec, 0x0, 0x0, 0x0, 0x75, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x79, 0x59, 0x7d, 0x58, 0x0, 0x0, 0x0, 0x26, 0x74, 0x52, 0x4e, 0x53, 0x0, 0xfc, 0xa5, 0xc9, 0xd, 0xf4, 0x7c, 0xd5, 0x8e, 0x7f, 0x26, 0x13, 0x78, 0xed, 0x47, 0xe0, 0xa0, 0x43, 0x8, 0xc5, 0xe9, 0xdc, 0xb4, 0xb0, 0x90, 0x88, 0x6b, 0x51, 0x29, 0x1f, 0xbe, 0x19, 0x94, 0x93, 0x37, 0x36, 0x1a, 0x58, 0x7b, 0xc0, 0x9a, 0x4f, 0x0, 0x0, 0x2, 0x10, 0x49, 0x44, 0x41, 0x54, 0x58, 0xc3, 0xed, 0x57, 0xd9, 0xb2, 0x82, 0x30, 0xc, 0x15, 0x91, 0x4d, 0x40, 0x40, 0x94, 0x4d, 0xb9, 0xee, 0xfd, 0xff, 0x4f, 0xbc, 0x93, 0x14, 0xd, 0xd3, 0x2, 0x41, 0x3b, 0xbe, 0x99, 0xd1, 0x7, 0xd2, 0xe4, 0x34, 0x3d, 0x4d, 0xd3, 0x74, 0xf1, 0x93, 0xaf, 0x4a, 0xbb, 0x69, 0xea, 0x73, 0x9a, 0x9e, 0xeb, 0x66, 0xd3, 0xbe, 0xef, 0x9d, 0xf9, 0xb6, 0x23, 0x5e, 0xe2, 0xd8, 0x7e, 0xf6, 0x8e, 0x77, 0x18, 0x79, 0xe8, 0x67, 0x75, 0x82, 0x1f, 0x5e, 0x14, 0xce, 0x74, 0x5f, 0x5, 0x3b, 0x74, 0x7e, 0x21, 0x3c, 0xbf, 0x76, 0xc1, 0x6a, 0x8e, 0xff, 0x61, 0x8f, 0xf6, 0xf8, 0x97, 0x42, 0xdf, 0xfb, 0x3, 0xef, 0xef, 0xb, 0x81, 0x53, 0xe2, 0xd2, 0x13, 0xbb, 0x2c, 0xed, 0x4, 0xc9, 0xe8, 0x94, 0x3e, 0x17, 0x7e, 0x81, 0x33, 0xc1, 0x2f, 0x77, 0x6f, 0xe1, 0x16, 0x74, 0xdb, 0xf0, 0xe6, 0xe6, 0xa8, 0x84, 0xb1, 0x62, 0x72, 0x19, 0x6b, 0x4f, 0x48, 0xcb, 0xd8, 0x5d, 0x2b, 0x23, 0x6e, 0x2c, 0xe4, 0x98, 0xb7, 0x9e, 0xf0, 0x8f, 0xa5, 0x8d, 0x55, 0x9d, 0xf4, 0xc1, 0x53, 0x65, 0xc9, 0xd1, 0x78, 0x14, 0x61, 0xd5, 0xcd, 0x9f, 0x1f, 0x87, 0xc7, 0x8f, 0x76, 0x17, 0xc3, 0xd8, 0x2a, 0xa, 0x49, 0xdd, 0x72, 0x3c, 0xc4, 0xa5, 0xa4, 0xb3, 0x18, 0xe3, 0x1f, 0xfd, 0xdd, 0x29, 0x92, 0x2, 0x89, 0xe0, 0xf, 0xee, 0xbf, 0x8c, 0x2f, 0x58, 0x4c, 0x4a, 0x20, 0xad, 0xe, 0x3, 0x4, 0xec, 0x81, 0x3d, 0x2d, 0xfe, 0xcd, 0x46, 0x5d, 0x5, 0x9a, 0xed, 0x57, 0x3a, 0x34, 0xe, 0xd8, 0xa, 0xea, 0x9f, 0x10, 0x7f, 0x8a, 0x2d, 0x30, 0x39, 0x10, 0x68, 0xb8, 0xc3, 0xd8, 0x14, 0xfe, 0x5d, 0x48, 0x1d, 0x85, 0x94, 0x23, 0xae, 0x61, 0xa7, 0x9e, 0xac, 0x8, 0x71, 0x2b, 0x45, 0x9b, 0xa, 0xc7, 0x11, 0xa9, 0xa2, 0xac, 0xd0, 0x34, 0x52, 0xb4, 0x1e, 0xcc, 0x15, 0xab, 0xf9, 0xf3, 0x0, 0xd2, 0x1f, 0x8a, 0xf2, 0x1e, 0x83, 0xad, 0xa7, 0xd4, 0xf, 0xdc, 0x1d, 0x7d, 0x7, 0xa3, 0x24, 0x89, 0x34, 0xa5, 0x8b, 0xfb, 0x9d, 0xe9, 0x39, 0x60, 0xd, 0xe4, 0xe8, 0x76, 0x3b, 0x90, 0xf1, 0x96, 0x9e, 0xb, 0x36, 0x44, 0x95, 0x2f, 0x66, 0x4a, 0x2e, 0x2c, 0x65, 0xc3, 0x5a, 0x87, 0x56, 0x30, 0x9d, 0x7, 0xb4, 0x6, 0xa7, 0xed, 0x9b, 0x9, 0x90, 0x1b, 0x29, 0x94, 0x3c, 0x50, 0xe4, 0x8a, 0xe6, 0x7d, 0xe8, 0x6, 0x21, 0x43, 0x9d, 0x43, 0x88, 0x55, 0x67, 0x31, 0xc4, 0x80, 0x9b, 0x9e, 0xa6, 0x6, 0xc3, 0x44, 0xe7, 0x6b, 0x9, 0xfa, 0xa5, 0xce, 0x6c, 0x2, 0xfa, 0xba, 0xa7, 0x39, 0x13, 0x2b, 0x1c, 0x0, 0x71, 0x7e, 0xe9, 0x67, 0x1c, 0x28, 0xca, 0xf9, 0x0, 0x25, 0xe8, 0x53, 0x63, 0x0, 0xe3, 0x25, 0x18, 0x93, 0xc8, 0x6d, 0x23, 0x1, 0xf0, 0xdb, 0x48, 0x89, 0xc4, 0x3, 0x50, 0x22, 0x31, 0xa9, 0x4c, 0x0, 0x7c, 0x2a, 0xd3, 0x61, 0xe2, 0x1, 0xe8, 0x30, 0x71, 0xc7, 0x99, 0x0, 0xf8, 0xe3, 0x4c, 0x5, 0x85, 0x7, 0xa0, 0x82, 0xc2, 0x95, 0x34, 0x2, 0xe0, 0x4b, 0x1a, 0x15, 0x55, 0x16, 0x80, 0x8a, 0x2a, 0x5b, 0xd6, 0xe9, 0x38, 0x33, 0x65, 0xdd, 0xe8, 0x62, 0xe1, 0xaf, 0xb6, 0x2c, 0x63, 0xae, 0x36, 0xe3, 0xcb, 0x55, 0xbf, 0xde, 0x83, 0xf, 0xaf, 0x77, 0xf3, 0x6, 0x83, 0x5a, 0x1c, 0x9b, 0x6d, 0x71, 0x3e, 0x6a, 0xb2, 0xee, 0x4c, 0x93, 0xc5, 0xb5, 0x79, 0x81, 0xd6, 0xe6, 0xf1, 0x8d, 0xe6, 0xf5, 0xd9, 0x68, 0x5e, 0x99, 0x46, 0xd3, 0xa0, 0xd5, 0x35, 0x6a, 0xb6, 0xcd, 0xdb, 0x7d, 0xf3, 0x7, 0x87, 0xf9, 0x93, 0x87, 0x7f, 0x74, 0x5d, 0xd2, 0xf4, 0x82, 0x8f, 0xae, 0x9f, 0x7c, 0x53, 0xfe, 0x1, 0x6f, 0xc7, 0x5c, 0x26, 0x6e, 0x29, 0x2b, 0x15, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82, 0x00 };
+const unsigned char defaultDialogIcon3Name[] = { 0x69, 0x6e, 0x66, 0x6f, 0x2d, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x32, 0x78, 0x00 };
+const unsigned char defaultDialogIcon3Length[] = { 0x31, 0x32, 0x39, 0x33, 0x00 };
+const unsigned char defaultDialogIcon3Data[] = { 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x80, 0x0, 0x0, 0x0, 0x80, 0x8, 0x3, 0x0, 0x0, 0x0, 0xf4, 0xe0, 0x91, 0xf9, 0x0, 0x0, 0x0, 0x93, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7a, 0x79, 0x23, 0x75, 0x0, 0x0, 0x0, 0x30, 0x74, 0x52, 0x4e, 0x53, 0x0, 0xfb, 0x55, 0x5, 0xe4, 0x40, 0xa, 0xb7, 0xd7, 0x62, 0x44, 0xe, 0xc0, 0x94, 0xb2, 0x2b, 0x68, 0x4e, 0xee, 0x39, 0xc6, 0x81, 0x48, 0x21, 0x89, 0x18, 0xe8, 0x33, 0xd0, 0xbd, 0xcb, 0x96, 0x8f, 0x13, 0x8b, 0xf6, 0xe1, 0xa8, 0x83, 0x7c, 0x71, 0x6c, 0x52, 0x26, 0x25, 0x1a, 0x3b, 0x5d, 0x23, 0x0, 0xd6, 0x57, 0x0, 0x0, 0x3, 0xf9, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0xec, 0x97, 0xd7, 0x76, 0xab, 0x40, 0xc, 0x45, 0x35, 0xa1, 0x99, 0x6a, 0x63, 0xc, 0xb8, 0x13, 0xdc, 0x4b, 0x7c, 0xa3, 0xff, 0xff, 0xba, 0xbb, 0x6e, 0x59, 0x78, 0x26, 0x60, 0x24, 0x8a, 0xb3, 0xf2, 0xe0, 0xfd, 0x3c, 0x1e, 0xb, 0x95, 0x73, 0x34, 0xf0, 0xe2, 0xc5, 0x8b, 0x17, 0x2f, 0xda, 0x63, 0xde, 0xae, 0xb, 0x23, 0xc, 0x8d, 0xc5, 0xf5, 0x66, 0xc2, 0xf7, 0xe2, 0x3a, 0x67, 0x7f, 0xa5, 0xa3, 0x84, 0xbe, 0xf2, 0xcf, 0x8e, 0xb, 0xdf, 0x81, 0x66, 0x1c, 0x26, 0x2, 0x2b, 0x11, 0x93, 0x83, 0xa1, 0xc1, 0x53, 0xd1, 0x92, 0xfd, 0x16, 0x6b, 0xd9, 0xee, 0x93, 0xe7, 0xc5, 0x30, 0xdc, 0xcc, 0x91, 0xc1, 0x7c, 0x33, 0x84, 0x67, 0xf0, 0xcb, 0x42, 0x36, 0x56, 0x4, 0x7d, 0xe3, 0x78, 0xd8, 0x8, 0xcf, 0xe9, 0x37, 0xf9, 0x1e, 0x36, 0xc6, 0xeb, 0xaf, 0x10, 0xe6, 0x54, 0x60, 0xb, 0xc4, 0xb4, 0x27, 0x79, 0x8, 0x77, 0xd8, 0x92, 0x5d, 0x8, 0x3d, 0xb0, 0xc1, 0xe, 0x4c, 0xbb, 0x8b, 0x5e, 0xf0, 0x30, 0xc3, 0xfa, 0x3a, 0xc8, 0x8e, 0xb6, 0x7d, 0xcc, 0x82, 0xb5, 0xfe, 0xb0, 0x46, 0x41, 0x47, 0x79, 0x4c, 0x7, 0x58, 0xc5, 0x32, 0x8e, 0x66, 0xa0, 0x30, 0x8b, 0xe2, 0x25, 0x56, 0x31, 0x48, 0xa1, 0x3, 0xc6, 0x18, 0x4b, 0x8, 0xef, 0x94, 0x3e, 0x88, 0xf6, 0xe4, 0x9, 0x2c, 0x31, 0x36, 0xa0, 0x35, 0xa3, 0xf2, 0x7d, 0x96, 0x9d, 0x43, 0xd, 0xb9, 0x6d, 0x95, 0x23, 0x1e, 0xb5, 0x15, 0x7e, 0x1f, 0xbf, 0x32, 0x89, 0x18, 0x8a, 0x39, 0xc1, 0xaf, 0xf8, 0x5a, 0xab, 0xff, 0xb7, 0x4a, 0xe5, 0xbc, 0x0, 0x8b, 0xcb, 0xa0, 0x94, 0xb7, 0x36, 0x11, 0xf8, 0xa8, 0x32, 0x1f, 0x69, 0xec, 0xd8, 0x47, 0x73, 0x54, 0xf1, 0x5b, 0xd4, 0x1f, 0x15, 0x44, 0x6c, 0x36, 0x12, 0xcf, 0x58, 0xa0, 0x42, 0xe3, 0x3e, 0x30, 0x84, 0xda, 0xca, 0x4e, 0x63, 0xf7, 0x52, 0x7, 0x48, 0x18, 0xd, 0xe7, 0x7f, 0xac, 0x56, 0xff, 0x3, 0x1a, 0xf3, 0x31, 0x50, 0x3f, 0x21, 0x6d, 0xa4, 0x7f, 0xea, 0x8f, 0x2d, 0xb7, 0x95, 0x88, 0x5a, 0xea, 0x47, 0x34, 0xb9, 0x44, 0xd5, 0xdf, 0x77, 0xad, 0xe5, 0x1c, 0xbf, 0xab, 0xaa, 0xc, 0x6c, 0xa6, 0x4a, 0xf5, 0x6c, 0x68, 0x8d, 0x2d, 0x5a, 0x39, 0x53, 0x88, 0x32, 0x36, 0x74, 0xc0, 0x46, 0x99, 0x90, 0x39, 0x42, 0x3b, 0x25, 0xff, 0xd0, 0x9, 0xa5, 0xa, 0x3b, 0x93, 0x59, 0x0, 0xbe, 0x86, 0xf1, 0xf5, 0x94, 0x5f, 0x84, 0xa1, 0xe0, 0xb7, 0x6e, 0xfe, 0xe9, 0xfb, 0x9f, 0x39, 0x7f, 0xa0, 0xc4, 0x10, 0x68, 0x3c, 0x79, 0x78, 0xeb, 0xe7, 0x3f, 0xd1, 0x11, 0x11, 0xf5, 0xa4, 0x5e, 0xf, 0x64, 0x49, 0xf1, 0x80, 0xc4, 0x91, 0x3, 0xae, 0xd7, 0xbf, 0x85, 0xf8, 0x7f, 0x6c, 0x51, 0x7f, 0xa3, 0x9c, 0x52, 0xa3, 0x51, 0x2, 0x62, 0xa8, 0x65, 0x59, 0x2c, 0x48, 0x50, 0xcb, 0x1, 0xef, 0xac, 0x48, 0x37, 0x97, 0xfd, 0xaf, 0xbe, 0x69, 0x6f, 0x58, 0x30, 0xab, 0x1f, 0x2b, 0xd9, 0x1b, 0xa9, 0x8d, 0xc2, 0xe2, 0x3b, 0x58, 0x82, 0x5, 0x9, 0xdf, 0x59, 0x2d, 0x62, 0x4, 0xe4, 0x9, 0xd0, 0xd8, 0x67, 0x89, 0xe6, 0xd6, 0x6, 0xc8, 0x3d, 0xbb, 0xc1, 0x3b, 0x17, 0x6a, 0xc4, 0xc7, 0xc5, 0xb0, 0x50, 0x62, 0x71, 0xc1, 0x3b, 0x9b, 0xda, 0x3b, 0xa5, 0x6a, 0x4d, 0x80, 0x62, 0xc4, 0xdf, 0x36, 0xa4, 0x3d, 0x51, 0xd7, 0x78, 0x65, 0xc5, 0x8, 0x48, 0x32, 0xfc, 0x4b, 0xc6, 0xd8, 0x54, 0x91, 0xd7, 0x30, 0x7b, 0xa5, 0x59, 0x68, 0xc2, 0x40, 0xd7, 0x3, 0xd5, 0x62, 0xe8, 0xe6, 0xde, 0xd7, 0x54, 0x60, 0x4b, 0x9b, 0x60, 0x77, 0x5b, 0xdc, 0x3e, 0xae, 0x81, 0x21, 0x89, 0x60, 0xe, 0xbd, 0x92, 0xb, 0x8e, 0x1a, 0x1e, 0x68, 0xd1, 0xa6, 0xa1, 0x15, 0x36, 0xe6, 0xf4, 0xea, 0x9, 0x7a, 0xe6, 0xc4, 0x98, 0x2f, 0x57, 0x4a, 0x53, 0xa, 0x3d, 0x93, 0x4a, 0xe5, 0x35, 0x69, 0x23, 0x5c, 0x2, 0xb, 0xf7, 0xcf, 0x3e, 0xe0, 0x2, 0xb, 0xe9, 0xf5, 0xfe, 0xc8, 0x64, 0xcf, 0x6a, 0x99, 0x68, 0x9c, 0x7f, 0xfb, 0x80, 0x3, 0x1c, 0x62, 0x2c, 0x38, 0x43, 0x35, 0x3e, 0xa1, 0x42, 0xc4, 0x3e, 0x40, 0x10, 0xd1, 0x2f, 0xc5, 0x95, 0xea, 0xaf, 0xfc, 0xa4, 0xae, 0x81, 0xc1, 0x8d, 0x5e, 0xa, 0xf4, 0x7b, 0x9b, 0x0, 0x83, 0x59, 0xb3, 0x78, 0x35, 0x71, 0xb7, 0x3, 0xa8, 0xc4, 0x44, 0xe2, 0x4, 0x77, 0x1f, 0x20, 0xbf, 0xf, 0x4d, 0x22, 0x47, 0xbc, 0x9c, 0xbe, 0x61, 0xc1, 0x1b, 0x30, 0x58, 0x53, 0x19, 0xbb, 0x12, 0xcf, 0x38, 0x32, 0x0, 0xfe, 0x83, 0xf3, 0x5a, 0xdd, 0xd4, 0x58, 0x90, 0x3d, 0x23, 0x80, 0xc, 0xb, 0x16, 0x94, 0x15, 0x1d, 0x9f, 0x11, 0xc0, 0x91, 0xb2, 0xa3, 0x90, 0xf0, 0x62, 0x32, 0x0, 0xbe, 0x23, 0x87, 0x3f, 0x33, 0x80, 0xdf, 0xed, 0x5b, 0xcb, 0xe, 0x82, 0x30, 0x10, 0x6c, 0x2, 0xed, 0x85, 0x44, 0xf, 0x84, 0x28, 0x26, 0x18, 0x4e, 0xdc, 0x14, 0xfe, 0xff, 0xeb, 0x8c, 0x21, 0x5e, 0x1c, 0xc9, 0xd2, 0x4e, 0x65, 0x29, 0xe9, 0x7c, 0xc1, 0x24, 0x4a, 0x77, 0xe7, 0xb1, 0xea, 0x3f, 0x81, 0xfa, 0x9f, 0x50, 0xfd, 0x33, 0x54, 0x7f, 0x88, 0xf0, 0x29, 0xe6, 0x9, 0xc8, 0x4f, 0xb1, 0x3c, 0x8c, 0x78, 0x2, 0x38, 0x8c, 0xd8, 0x71, 0x8c, 0x4, 0xd8, 0x71, 0x8c, 0xb, 0x9, 0x43, 0x40, 0x5e, 0x48, 0xd8, 0x95, 0xc, 0x9, 0xb0, 0x2b, 0x19, 0x2e, 0xa5, 0xc, 0x1, 0x79, 0x29, 0x65, 0xd7, 0x72, 0x24, 0x40, 0xaf, 0xe5, 0x28, 0x4c, 0x8, 0x2, 0xa2, 0x30, 0xa1, 0xa5, 0x19, 0x12, 0xe0, 0xa5, 0x19, 0x8a, 0x53, 0x82, 0x80, 0x24, 0x4e, 0x69, 0x79, 0x8e, 0x4, 0x78, 0x79, 0x8e, 0x6, 0x5, 0x41, 0x40, 0x32, 0x28, 0x78, 0x8b, 0x6, 0x9, 0xf0, 0x16, 0xd, 0x9a, 0x54, 0xc, 0x1, 0xd9, 0xa4, 0xe2, 0x6d, 0x3a, 0x24, 0xc0, 0xdb, 0x74, 0x68, 0x54, 0xf2, 0x4, 0xd0, 0xa8, 0xdc, 0xb7, 0x55, 0x6b, 0xea, 0xf5, 0x66, 0x75, 0x4b, 0x98, 0xd5, 0x91, 0xed, 0xfa, 0x3b, 0x67, 0xd7, 0xf3, 0x81, 0xc5, 0x99, 0x8, 0x2c, 0x88, 0xc8, 0x6, 0x2c, 0x1a, 0xef, 0xc8, 0x86, 0xf, 0xad, 0xaa, 0xb1, 0xef, 0xc7, 0xca, 0x27, 0xb4, 0x4a, 0x21, 0xb6, 0xd3, 0xf, 0x2e, 0xd5, 0xa3, 0x5b, 0xfd, 0xf0, 0x5a, 0x3f, 0xbe, 0xd7, 0x2f, 0x30, 0xfc, 0xa1, 0xc2, 0x71, 0xbb, 0xa4, 0x55, 0x62, 0xc1, 0x1a, 0xcf, 0xe0, 0x57, 0xe3, 0x19, 0xbe, 0x6b, 0x3c, 0xe9, 0x15, 0x99, 0xa2, 0x56, 0xb9, 0x4e, 0x45, 0xac, 0x32, 0xdb, 0x33, 0xb0, 0xcc, 0x96, 0x66, 0x9d, 0x6f, 0x7, 0x85, 0x46, 0x8f, 0x4a, 0xe7, 0x63, 0xb9, 0xd2, 0x99, 0x76, 0xa9, 0x75, 0x9e, 0x4c, 0xe1, 0xb8, 0x1e, 0xa1, 0xd8, 0xac, 0x5f, 0xed, 0xd6, 0x2f, 0xb7, 0xbf, 0x61, 0xbb, 0xc9, 0xb, 0x9d, 0x35, 0xb1, 0x51, 0xf3, 0x7, 0xe, 0xfc, 0x89, 0x47, 0x39, 0xad, 0x40, 0x9, 0x27, 0x1e, 0x87, 0x39, 0x72, 0x99, 0x39, 0xd8, 0x66, 0xf9, 0xcc, 0xa7, 0xb1, 0x85, 0xd9, 0x2, 0xee, 0xf7, 0xa1, 0x93, 0x33, 0xdb, 0xc2, 0xb5, 0x9f, 0x53, 0xaf, 0xd6, 0x99, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x60, 0xbc, 0x0, 0xd9, 0xfc, 0x9e, 0xf5, 0xee, 0xae, 0x37, 0x12, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82, 0x00 };
+const unsigned char defaultDialogIcon4Name[] = { 0x71, 0x75, 0x65, 0x73, 0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x64, 0x61, 0x72, 0x6b, 0x00 };
+const unsigned char defaultDialogIcon4Length[] = { 0x39, 0x34, 0x31, 0x00 };
+const unsigned char defaultDialogIcon4Data[] = { 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x40, 0x0, 0x0, 0x0, 0x40, 0x8, 0x3, 0x0, 0x0, 0x0, 0x9d, 0xb7, 0x81, 0xec, 0x0, 0x0, 0x0, 0x99, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xd5, 0x1d, 0x4, 0x54, 0x0, 0x0, 0x0, 0x32, 0x74, 0x52, 0x4e, 0x53, 0x0, 0xf9, 0x1c, 0xe6, 0xb1, 0x3b, 0x17, 0xc9, 0xad, 0x6, 0x8f, 0x4e, 0x4b, 0x40, 0xf6, 0xe3, 0xe0, 0xc1, 0x20, 0x11, 0x62, 0x54, 0x34, 0x30, 0x2b, 0x5d, 0xd6, 0xd0, 0x98, 0x76, 0x65, 0xb, 0x9b, 0x92, 0x6d, 0x48, 0x2, 0x9, 0x3, 0x9c, 0xb5, 0x9d, 0xed, 0xe8, 0xbb, 0x78, 0xdc, 0x83, 0x71, 0x9f, 0x76, 0x53, 0x1c, 0x31, 0x0, 0x0, 0x2, 0x91, 0x49, 0x44, 0x41, 0x54, 0x58, 0xc3, 0xed, 0x57, 0x6b, 0x7b, 0xaa, 0x30, 0xc, 0x3e, 0xdc, 0x4, 0x41, 0x85, 0x71, 0x13, 0x54, 0x18, 0x53, 0xa7, 0xce, 0xcb, 0xb6, 0xb3, 0xff, 0xff, 0xe3, 0x8e, 0xa4, 0xa5, 0x29, 0x4, 0xe, 0xee, 0xe9, 0xb3, 0x6f, 0xcb, 0x27, 0xdb, 0x92, 0x34, 0x79, 0xf3, 0x26, 0x8d, 0x7f, 0x7e, 0xe5, 0x47, 0x65, 0xaf, 0xa7, 0x5e, 0x5c, 0x14, 0xb1, 0x97, 0xea, 0xfb, 0xef, 0x6b, 0x4f, 0x3c, 0xd7, 0xf6, 0xb5, 0x2f, 0x10, 0xcd, 0xb7, 0x5d, 0x6f, 0xf2, 0x2d, 0x75, 0x6b, 0x13, 0x7c, 0x75, 0x24, 0xd8, 0x58, 0xf, 0xab, 0xcf, 0xcd, 0xfa, 0x6a, 0x22, 0x9a, 0x39, 0x7f, 0x48, 0x3d, 0x3c, 0xa, 0x75, 0x62, 0xe2, 0x18, 0x8e, 0xeb, 0xcf, 0x2, 0x59, 0xc3, 0x58, 0xad, 0xc, 0xd9, 0x5e, 0x30, 0x1b, 0xd3, 0xdf, 0x2e, 0x9a, 0x6f, 0xd, 0xa7, 0xb4, 0x32, 0x3d, 0x8a, 0xf4, 0xcc, 0x2a, 0x1d, 0xa3, 0xd9, 0x5d, 0x6c, 0xff, 0xab, 0xfe, 0xfc, 0x22, 0xe2, 0x4d, 0x74, 0xf9, 0x40, 0x4f, 0x4, 0x2e, 0x2f, 0xcf, 0xc3, 0xfa, 0xaf, 0xe, 0xff, 0xe8, 0x69, 0xd7, 0x13, 0xdb, 0x13, 0x3f, 0x74, 0x5e, 0x7, 0xd, 0xf0, 0xfb, 0x8d, 0x7c, 0xda, 0x77, 0x3a, 0xcd, 0xd, 0xee, 0xc3, 0x60, 0xfc, 0xec, 0x7c, 0xbd, 0x1c, 0xfa, 0x60, 0xb9, 0x66, 0x5f, 0x6c, 0x7, 0xf0, 0x67, 0xf8, 0x99, 0x13, 0x54, 0x28, 0x1c, 0xdb, 0x36, 0x6f, 0x68, 0x70, 0x62, 0x32, 0x24, 0x7b, 0x73, 0x11, 0xfa, 0x4c, 0x5f, 0x60, 0xa4, 0x57, 0xb, 0x8e, 0xfc, 0xdf, 0x50, 0xa0, 0xcc, 0x2c, 0xf8, 0x7d, 0x7c, 0x78, 0x63, 0xfe, 0x8b, 0xfb, 0xd3, 0x15, 0xa6, 0xff, 0xdd, 0x12, 0x56, 0x59, 0x14, 0x6f, 0x3d, 0xfc, 0xd5, 0x0, 0x3f, 0xe1, 0x6e, 0xe6, 0xa3, 0xbe, 0xbc, 0xbf, 0x4, 0x24, 0x35, 0xc2, 0xea, 0x3, 0xf3, 0x2d, 0x17, 0x90, 0x43, 0xd2, 0x50, 0x6c, 0x91, 0xbb, 0x9c, 0x45, 0x7a, 0xe8, 0xd6, 0x9f, 0x6, 0xf9, 0x17, 0xf9, 0x4b, 0x38, 0x21, 0x5c, 0x97, 0x5b, 0x8a, 0x5, 0x59, 0x60, 0x43, 0xeb, 0xd6, 0xe6, 0x6, 0x76, 0x91, 0x3f, 0x27, 0x58, 0x7f, 0xde, 0xd, 0x4e, 0x3f, 0x99, 0x6d, 0xd1, 0x54, 0x76, 0xb0, 0xde, 0x74, 0xfa, 0x47, 0x0, 0x7e, 0x21, 0x75, 0xcf, 0xf5, 0xba, 0x62, 0x8b, 0xaa, 0xfe, 0x7d, 0x16, 0xc0, 0xef, 0x21, 0xda, 0xa0, 0xdd, 0x61, 0x3c, 0x70, 0x33, 0x11, 0xeb, 0x14, 0x32, 0x38, 0x6f, 0xf0, 0x45, 0x9f, 0x31, 0x3c, 0xaf, 0x65, 0xc0, 0x5, 0xa8, 0xf5, 0x76, 0x4e, 0xce, 0xfc, 0x92, 0x10, 0xac, 0x61, 0x78, 0x3a, 0x24, 0xc2, 0x6d, 0xd1, 0xdc, 0x86, 0x2a, 0x91, 0x42, 0x7a, 0xbf, 0xaf, 0x4f, 0x1c, 0xd2, 0x59, 0x17, 0x35, 0x7, 0xf2, 0x22, 0x17, 0x8c, 0xe, 0x49, 0x2f, 0x65, 0x5a, 0xd8, 0xe7, 0x53, 0xc8, 0x33, 0xc, 0x80, 0x5e, 0xa4, 0x98, 0x4b, 0x60, 0xa3, 0x5c, 0xef, 0x29, 0x0, 0x6b, 0xb5, 0x9c, 0x8a, 0xf6, 0xd, 0xa3, 0x59, 0x11, 0xcb, 0x39, 0x7, 0x97, 0xd2, 0x2e, 0x86, 0x5a, 0x46, 0xf9, 0x99, 0x7d, 0x9c, 0x2e, 0xac, 0x1e, 0x52, 0x79, 0x17, 0xee, 0x93, 0x2b, 0x2a, 0x66, 0x18, 0x52, 0x7d, 0x80, 0x8b, 0x90, 0x9f, 0xa1, 0x18, 0x4b, 0x3b, 0x45, 0xbd, 0xb1, 0x8a, 0x88, 0x81, 0x8f, 0x46, 0xff, 0xda, 0xca, 0x7a, 0x4, 0x75, 0x56, 0x3c, 0x60, 0xe0, 0xd8, 0x74, 0x31, 0x38, 0x22, 0x6, 0xc6, 0x43, 0xa8, 0x0, 0x9b, 0x75, 0x89, 0x19, 0x23, 0x21, 0x10, 0x10, 0xa9, 0x1, 0x7, 0xdb, 0x30, 0x1, 0x91, 0xa4, 0x91, 0x18, 0x20, 0x65, 0x43, 0xd2, 0x48, 0x88, 0x44, 0x30, 0x38, 0xe2, 0x9a, 0x12, 0x89, 0x52, 0x99, 0x94, 0x8, 0x92, 0x9e, 0x52, 0x99, 0x16, 0x53, 0x47, 0x76, 0x72, 0x15, 0x91, 0x62, 0x1a, 0x2e, 0x67, 0x94, 0xd8, 0xb6, 0x11, 0x6c, 0x5a, 0xce, 0xb4, 0xa1, 0x10, 0x39, 0xc8, 0xbd, 0x8f, 0x36, 0x14, 0xda, 0xd2, 0xc6, 0x85, 0xb6, 0x34, 0xda, 0x54, 0x51, 0xa2, 0x3c, 0x47, 0x12, 0x92, 0xa6, 0x3a, 0xd8, 0xd6, 0x11, 0x2e, 0xfb, 0x8e, 0x36, 0x42, 0x4b, 0xda, 0xfa, 0xc0, 0xc3, 0x82, 0x72, 0xab, 0xf7, 0x6e, 0xed, 0x7, 0xf6, 0x42, 0x1f, 0x16, 0xfa, 0xb4, 0x51, 0x1e, 0xd0, 0xa7, 0x6d, 0xfc, 0x71, 0x5, 0xb7, 0xf0, 0x32, 0xfa, 0xb8, 0xe, 0x3f, 0xef, 0x28, 0xc9, 0xf5, 0x9a, 0xc8, 0xf7, 0xe3, 0xf3, 0xae, 0x36, 0x60, 0x28, 0x8f, 0x38, 0xe3, 0x43, 0xd6, 0x6c, 0x64, 0xc8, 0x52, 0x1b, 0xf3, 0x14, 0x7, 0x4d, 0xd5, 0x51, 0x57, 0x6d, 0xd8, 0xae, 0x42, 0xc5, 0x71, 0x5f, 0xf1, 0xf, 0x87, 0xe2, 0x5f, 0x1e, 0xc5, 0x3f, 0x5d, 0xbf, 0xf2, 0x93, 0xf2, 0xf, 0x45, 0x13, 0xb6, 0x9d, 0x6, 0x38, 0x84, 0xb9, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82, 0x00 };
+const unsigned char defaultDialogIcon5Name[] = { 0x71, 0x75, 0x65, 0x73, 0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x64, 0x61, 0x72, 0x6b, 0x32, 0x78, 0x00 };
+const unsigned char defaultDialogIcon5Length[] = { 0x31, 0x35, 0x35, 0x37, 0x00 };
+const unsigned char defaultDialogIcon5Data[] = { 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x80, 0x0, 0x0, 0x0, 0x80, 0x8, 0x3, 0x0, 0x0, 0x0, 0xf4, 0xe0, 0x91, 0xf9, 0x0, 0x0, 0x0, 0x9f, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xa, 0x77, 0x79, 0xb8, 0x0, 0x0, 0x0, 0x34, 0x74, 0x52, 0x4e, 0x53, 0x0, 0xfb, 0x2, 0xa, 0x40, 0x62, 0xe5, 0x8a, 0x82, 0xe, 0x6, 0xb8, 0x2b, 0x19, 0x44, 0xed, 0xd9, 0x26, 0xb1, 0x94, 0x4e, 0x39, 0xc6, 0xf6, 0xbf, 0x55, 0x48, 0x21, 0x67, 0x33, 0xe0, 0xa8, 0x6c, 0xe8, 0xc2, 0x97, 0x90, 0x14, 0xd4, 0xb5, 0x3b, 0xd1, 0xcb, 0x7b, 0x52, 0xbc, 0x9e, 0xef, 0x71, 0x72, 0x5c, 0x1d, 0xd8, 0xaf, 0x95, 0x64, 0x0, 0x0, 0x4, 0xf1, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0xec, 0x97, 0xdb, 0x96, 0xa2, 0x40, 0xc, 0x45, 0x23, 0x20, 0x20, 0x88, 0x82, 0x22, 0xd8, 0xde, 0xef, 0xed, 0xa5, 0x45, 0xa7, 0x27, 0xff, 0xff, 0x6d, 0xf3, 0x30, 0x6b, 0x69, 0xa, 0x52, 0x1d, 0x40, 0xed, 0x27, 0xf7, 0x6b, 0x61, 0xaa, 0xea, 0x24, 0x27, 0x29, 0xe1, 0xcd, 0x9b, 0x37, 0x6f, 0xde, 0xd4, 0xc7, 0xc, 0xa2, 0xa9, 0x15, 0xc7, 0xd6, 0x34, 0xa, 0x4c, 0xf8, 0x5d, 0x5a, 0x9d, 0x45, 0xff, 0x6c, 0x23, 0xc1, 0x3e, 0xf7, 0x17, 0x9d, 0x16, 0xfc, 0x6, 0x9e, 0xe5, 0x26, 0xd, 0x64, 0x69, 0x24, 0xae, 0xe5, 0xc1, 0x4b, 0x31, 0x46, 0xf3, 0x14, 0x7f, 0x24, 0x9d, 0x8f, 0xc, 0x78, 0x15, 0x6d, 0x67, 0x89, 0x25, 0x58, 0x3a, 0x6d, 0x78, 0x5, 0x7b, 0x1f, 0x4b, 0xe3, 0xf, 0xe0, 0xd9, 0x74, 0x86, 0x58, 0x89, 0x61, 0xe7, 0xb9, 0xe2, 0xf, 0xb1, 0x32, 0xc3, 0xe7, 0x25, 0xc2, 0x74, 0x1a, 0x58, 0x83, 0x86, 0x63, 0xc2, 0x53, 0x88, 0x67, 0x58, 0x93, 0x59, 0xfc, 0xc, 0xe7, 0x39, 0xf8, 0x0, 0xce, 0xc3, 0x9e, 0x6c, 0x7d, 0x6a, 0x15, 0xb6, 0x8f, 0xbd, 0xf5, 0xa9, 0xd9, 0x3c, 0xad, 0x7b, 0x47, 0x5b, 0x9b, 0xa3, 0xde, 0x83, 0xed, 0x71, 0xbc, 0x43, 0x8e, 0x83, 0x3b, 0x8, 0xc, 0x45, 0xa7, 0x60, 0xe0, 0x1e, 0x90, 0x63, 0x37, 0x86, 0x7, 0xb0, 0xba, 0xcc, 0xcd, 0x57, 0x57, 0x4d, 0xcc, 0xf1, 0x75, 0xc5, 0x28, 0xd1, 0xb5, 0xa0, 0x36, 0x93, 0x62, 0x3c, 0xbf, 0xb9, 0x85, 0x1f, 0xd8, 0x36, 0xfd, 0xe2, 0x89, 0x27, 0x75, 0xc7, 0x4e, 0x1f, 0xf3, 0x24, 0x3, 0x10, 0xd9, 0x27, 0x98, 0xa7, 0xef, 0xd5, 0xda, 0xbf, 0x50, 0x7e, 0xe1, 0x17, 0x94, 0xe2, 0x2b, 0xc4, 0x1c, 0x9f, 0x75, 0x4e, 0x90, 0xbf, 0xff, 0x72, 0x52, 0x3a, 0x8a, 0x37, 0x59, 0xe6, 0x35, 0xa8, 0x91, 0xff, 0x5c, 0x22, 0x5d, 0x13, 0x2a, 0x60, 0xba, 0xb9, 0xf2, 0xa9, 0x5c, 0x7, 0x96, 0x1a, 0xa0, 0xdb, 0xa9, 0x3c, 0xbd, 0xba, 0xea, 0x5, 0xac, 0x8a, 0xfe, 0x57, 0x7f, 0x1e, 0x46, 0x50, 0x99, 0x28, 0x54, 0xaf, 0x30, 0xae, 0xd4, 0xff, 0x76, 0xaa, 0xf7, 0x5a, 0xb5, 0x9a, 0xa8, 0xea, 0xc8, 0x5d, 0x85, 0x20, 0x86, 0x6a, 0x80, 0x8d, 0xa1, 0xf1, 0x7c, 0x36, 0xc, 0xd3, 0x74, 0xb6, 0x9a, 0x2f, 0x2, 0x3e, 0xcc, 0x6, 0x29, 0x3d, 0x3, 0xca, 0xe2, 0x28, 0xd9, 0x6b, 0xb2, 0xc1, 0x9b, 0x4a, 0xd7, 0x3b, 0x2e, 0x58, 0x8b, 0x34, 0x95, 0x4a, 0x72, 0xa0, 0x24, 0x31, 0x52, 0xd8, 0xfd, 0x47, 0xbb, 0xc2, 0xe8, 0xfd, 0x60, 0x4f, 0x80, 0x94, 0xb8, 0xa4, 0x85, 0x66, 0x8a, 0xfe, 0x5c, 0x76, 0x7b, 0xc8, 0xb0, 0xe2, 0x12, 0xb1, 0x51, 0xe, 0x69, 0x56, 0x4f, 0x80, 0x6f, 0x8, 0x23, 0x92, 0x30, 0x9b, 0x32, 0xa9, 0xf2, 0x2b, 0x27, 0xa1, 0x4d, 0xf3, 0x16, 0x32, 0xa5, 0x3b, 0xed, 0xa2, 0x86, 0xb4, 0xc3, 0xa8, 0x15, 0xd2, 0x7a, 0x6a, 0x83, 0xcc, 0x90, 0x9a, 0x97, 0xf1, 0x7f, 0x60, 0xa3, 0x96, 0xb, 0xf3, 0x7d, 0x44, 0xcf, 0x3b, 0x4, 0x91, 0xe, 0x3d, 0x30, 0x73, 0x23, 0xf3, 0x88, 0x3f, 0x10, 0x6e, 0x99, 0x88, 0x54, 0x52, 0xab, 0x92, 0x0, 0xae, 0x30, 0xa3, 0x18, 0xe6, 0x50, 0xc4, 0xad, 0x22, 0xc1, 0x9e, 0xce, 0x3f, 0x93, 0x11, 0x54, 0x7a, 0xa1, 0xf, 0x18, 0xd1, 0x96, 0xec, 0x3a, 0x8f, 0x2f, 0x4c, 0xb0, 0x9c, 0x1, 0xd3, 0x24, 0x49, 0x73, 0x66, 0x84, 0x22, 0xb, 0xfa, 0x34, 0x10, 0x2c, 0x40, 0xf3, 0xe9, 0x31, 0xe, 0x40, 0xca, 0xa6, 0x6d, 0x0, 0x18, 0xed, 0xd, 0x52, 0x98, 0xba, 0xf1, 0xa8, 0x13, 0xda, 0xa5, 0x7b, 0xc0, 0x97, 0xb0, 0x3e, 0xbb, 0x15, 0x94, 0x45, 0x5b, 0xd7, 0x9a, 0x7b, 0x23, 0x95, 0xed, 0x5, 0x6, 0xc9, 0x56, 0x2, 0xc, 0x21, 0xb1, 0x68, 0x40, 0xac, 0x49, 0xac, 0xb6, 0xe4, 0x66, 0xe, 0x79, 0x27, 0xda, 0x6, 0xe8, 0x19, 0x9, 0xd5, 0x12, 0x91, 0xf5, 0x6f, 0x20, 0x7c, 0xd3, 0x1f, 0xa, 0xb5, 0x3d, 0x2, 0x3d, 0x73, 0xd2, 0x83, 0x81, 0xe1, 0x43, 0xbb, 0xee, 0xb, 0xaf, 0x2f, 0x9f, 0x3a, 0x55, 0x8b, 0x97, 0xa, 0x43, 0xf0, 0xf, 0xde, 0xb8, 0x6a, 0x57, 0x5c, 0x61, 0x2c, 0xa6, 0x1e, 0xe8, 0xb0, 0x48, 0x13, 0xdc, 0xa, 0x35, 0xba, 0xd7, 0x6a, 0x9c, 0x1, 0xc3, 0xb6, 0x51, 0xa6, 0x1b, 0xba, 0xd4, 0xce, 0x1c, 0xd9, 0xfd, 0x80, 0x26, 0x28, 0xb4, 0x24, 0xa7, 0xaf, 0x58, 0x89, 0xf4, 0xb5, 0x7a, 0x15, 0x4e, 0xb8, 0xd3, 0x37, 0x90, 0x39, 0x8, 0xd9, 0x4b, 0x40, 0x43, 0x8b, 0xc8, 0x34, 0x16, 0x5c, 0x92, 0xe9, 0x73, 0xbc, 0x1, 0x8e, 0x31, 0x12, 0xf5, 0xe4, 0x41, 0x78, 0x10, 0x3a, 0xf5, 0xe5, 0x2f, 0xa8, 0xac, 0xf1, 0xc6, 0x9, 0x58, 0xe, 0xb4, 0x59, 0xf2, 0x2c, 0xe4, 0x34, 0x5, 0x87, 0xff, 0xfb, 0xc7, 0xf9, 0xc, 0xa4, 0x24, 0xbc, 0x58, 0x60, 0xb, 0xf9, 0xdf, 0xe0, 0x40, 0xeb, 0xd4, 0xd3, 0xea, 0xb2, 0xcb, 0xf2, 0xf7, 0x37, 0x8e, 0xb2, 0xc0, 0x3, 0xf9, 0x9f, 0xe2, 0x19, 0x6f, 0x4, 0x50, 0x5, 0x33, 0xc3, 0x3b, 0x67, 0x9d, 0x78, 0xf2, 0x27, 0xf6, 0xfd, 0x16, 0x6, 0x94, 0x80, 0xce, 0x22, 0xd9, 0xe5, 0xc6, 0xbd, 0xc4, 0x6d, 0xcd, 0x3d, 0x90, 0xf9, 0x42, 0xc0, 0xdc, 0x5f, 0xe7, 0x21, 0x52, 0x7c, 0x0, 0xf1, 0x7e, 0x68, 0x4a, 0x1a, 0x1d, 0xa1, 0x14, 0xad, 0xac, 0x81, 0x79, 0xa6, 0xa0, 0xe3, 0x28, 0x64, 0x98, 0x8e, 0xba, 0x5e, 0xb9, 0xfd, 0x67, 0xf2, 0x9b, 0x90, 0x7f, 0x4c, 0x45, 0xc0, 0x31, 0x55, 0x1f, 0x15, 0x32, 0x19, 0x16, 0x68, 0x44, 0xa0, 0x65, 0x2d, 0xc9, 0x64, 0x29, 0xbd, 0x44, 0xc6, 0x2c, 0xea, 0x9f, 0x8e, 0x40, 0xcf, 0x49, 0x2a, 0xd4, 0x58, 0x99, 0xc5, 0x32, 0xfb, 0xe2, 0xfe, 0x4c, 0x60, 0xb6, 0x5b, 0xc7, 0x4f, 0x39, 0xc0, 0x7, 0xe6, 0xb8, 0xfc, 0x6b, 0xdf, 0x8e, 0x5a, 0x12, 0x6, 0xa3, 0x30, 0x8e, 0x4f, 0x93, 0x5, 0x61, 0x8, 0xda, 0x8, 0x86, 0x91, 0xa0, 0x92, 0x17, 0x51, 0x24, 0x7d, 0xff, 0xcf, 0x16, 0xc6, 0x18, 0xc1, 0x5e, 0xfb, 0xb9, 0x8e, 0x31, 0x27, 0xfb, 0x5f, 0x7b, 0x71, 0x64, 0x7b, 0xcf, 0x7b, 0xce, 0xf3, 0x3c, 0xdb, 0x65, 0x81, 0x2, 0xf4, 0x8, 0x5c, 0xc0, 0xec, 0xd8, 0x1, 0xf0, 0x23, 0xf0, 0x4b, 0xe8, 0x2, 0x46, 0x6f, 0x5b, 0xfc, 0x1e, 0x2f, 0x21, 0x8e, 0x21, 0xa, 0x78, 0x7c, 0xc6, 0xdf, 0xc7, 0x31, 0x44, 0x23, 0x62, 0x1, 0x1b, 0x8, 0x50, 0x68, 0x44, 0x6a, 0xc5, 0x2e, 0xa0, 0x21, 0xcf, 0xa8, 0x15, 0xfb, 0x32, 0xa, 0x15, 0xe0, 0xcb, 0xc8, 0xd7, 0x71, 0xa8, 0x0, 0x5f, 0xc7, 0x1e, 0x48, 0x42, 0x5, 0x78, 0x20, 0xf1, 0x48, 0x16, 0x2b, 0xc0, 0x23, 0x99, 0x87, 0x52, 0xf3, 0xfa, 0xcb, 0x22, 0xed, 0xa1, 0xd4, 0x63, 0x39, 0x99, 0x62, 0xe7, 0xc7, 0x58, 0xce, 0xc5, 0x84, 0x8c, 0x67, 0x75, 0x13, 0x6e, 0x1c, 0x1a, 0x2f, 0x26, 0x5e, 0xcd, 0xcc, 0x12, 0x77, 0x17, 0x56, 0x33, 0x2e, 0xa7, 0x66, 0xd, 0x3f, 0x6, 0xcb, 0x29, 0xd7, 0x73, 0x53, 0xce, 0xf3, 0x7c, 0x5e, 0x66, 0x0, 0xeb, 0x39, 0x4, 0x8a, 0x0, 0x10, 0x28, 0x2c, 0xd1, 0x84, 0xb0, 0x44, 0x63, 0x91, 0x2a, 0x86, 0x45, 0x2a, 0xcb, 0x74, 0x31, 0x2c, 0xd3, 0x59, 0xa8, 0xc, 0x61, 0xa1, 0xd2, 0x52, 0xad, 0xd8, 0xee, 0x17, 0x8b, 0xbd, 0xe, 0xac, 0xa5, 0xda, 0x9f, 0x14, 0x69, 0xb1, 0x3a, 0x4d, 0x99, 0x7f, 0x3f, 0x54, 0x9c, 0x43, 0x8b, 0xd5, 0x96, 0xeb, 0xd3, 0x3c, 0x8d, 0xaa, 0xa6, 0x85, 0x79, 0x10, 0x72, 0x3d, 0xc, 0xb, 0xdc, 0x6f, 0xbe, 0x3b, 0x6d, 0x58, 0xd8, 0xb2, 0x49, 0x73, 0xef, 0x1, 0xca, 0x96, 0x8d, 0x4d, 0x2b, 0x74, 0x2d, 0xf4, 0x16, 0x9b, 0x56, 0xb6, 0xed, 0x62, 0xf3, 0x80, 0x6d, 0x3b, 0x1b, 0x97, 0xc7, 0x18, 0xbf, 0xd7, 0x4b, 0x61, 0x5d, 0xa5, 0x8c, 0xcb, 0x88, 0x75, 0xdb, 0x64, 0x89, 0x86, 0x1, 0xeb, 0x36, 0x62, 0x5e, 0x57, 0xac, 0xb1, 0x49, 0xc2, 0xbc, 0x8e, 0xd8, 0xf7, 0x15, 0xf, 0x87, 0x79, 0xa0, 0xfe, 0x5f, 0xb4, 0xef, 0xfb, 0x13, 0x60, 0xe8, 0x3e, 0xc2, 0xd1, 0x7d, 0x88, 0xa5, 0xfb, 0x18, 0x4f, 0x22, 0xc8, 0xb4, 0x3a, 0x3d, 0xc8, 0xb4, 0x6a, 0x4, 0x99, 0xba, 0x8e, 0x72, 0x8d, 0xcf, 0x15, 0x66, 0xdb, 0xfd, 0x29, 0xcc, 0xb6, 0xb9, 0xeb, 0x67, 0x9c, 0xaf, 0x7d, 0xa0, 0xf1, 0x23, 0x1d, 0x68, 0xec, 0x73, 0xa4, 0xb3, 0x4e, 0xec, 0x4, 0x42, 0xad, 0x7d, 0x8f, 0xf5, 0x76, 0x1f, 0x6c, 0xbe, 0x80, 0x68, 0x77, 0xf7, 0xe1, 0xf6, 0x3, 0x93, 0xb6, 0xf1, 0xfe, 0x49, 0x76, 0x6e, 0x8a, 0xba, 0x35, 0x9b, 0x97, 0x22, 0xfb, 0xf, 0xa6, 0xb7, 0xf9, 0xe7, 0x9, 0xe4, 0xc9, 0x4f, 0x3c, 0xae, 0xe2, 0x23, 0x97, 0xb, 0xf8, 0xcc, 0xa7, 0xe2, 0x26, 0xfd, 0xa1, 0x53, 0x9b, 0x53, 0xd7, 0xf3, 0x4f, 0xbd, 0x6, 0x6, 0x6, 0x6, 0xae, 0x8a, 0x2f, 0x2e, 0x60, 0x3a, 0x41, 0x7b, 0x3f, 0x8e, 0x53, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82, 0x00 };
+const unsigned char defaultDialogIcon6Name[] = { 0x71, 0x75, 0x65, 0x73, 0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x00 };
+const unsigned char defaultDialogIcon6Length[] = { 0x39, 0x33, 0x30, 0x00 };
+const unsigned char defaultDialogIcon6Data[] = { 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x40, 0x0, 0x0, 0x0, 0x40, 0x8, 0x3, 0x0, 0x0, 0x0, 0x9d, 0xb7, 0x81, 0xec, 0x0, 0x0, 0x0, 0x96, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3a, 0xb, 0xcd, 0x2a, 0x0, 0x0, 0x0, 0x31, 0x74, 0x52, 0x4e, 0x53, 0x0, 0xf9, 0x1c, 0xe6, 0xb1, 0x4d, 0x3b, 0x17, 0xc9, 0xad, 0x49, 0x6, 0x8f, 0x40, 0xf6, 0xe3, 0xe0, 0xc1, 0x20, 0x11, 0x62, 0x54, 0x34, 0x30, 0x2b, 0x5d, 0xd6, 0xd0, 0x98, 0x76, 0x65, 0xb, 0x9b, 0x92, 0x6d, 0x2, 0x9, 0x3, 0x9c, 0xb5, 0x9d, 0xed, 0xe8, 0xbb, 0x79, 0xdc, 0x83, 0x71, 0x9f, 0x7a, 0xba, 0x9d, 0xd4, 0x0, 0x0, 0x2, 0x8a, 0x49, 0x44, 0x41, 0x54, 0x58, 0xc3, 0xec, 0x53, 0xdb, 0x62, 0x82, 0x30, 0xc, 0x5d, 0xcb, 0x5d, 0x51, 0x10, 0x10, 0x11, 0x1, 0x2f, 0xa8, 0x88, 0x9b, 0x3a, 0xfe, 0xff, 0xe7, 0xa6, 0x69, 0x9, 0x2d, 0x97, 0xa9, 0xf, 0x7b, 0x5b, 0x9e, 0x48, 0xd2, 0x13, 0x92, 0x73, 0x92, 0x8f, 0x7f, 0xfb, 0x53, 0xcb, 0x69, 0xa8, 0x5, 0x69, 0x1a, 0x68, 0x21, 0xcd, 0xdf, 0x47, 0x1b, 0x9a, 0x6d, 0x3a, 0xa4, 0x2, 0x23, 0x8e, 0x69, 0x6b, 0xc6, 0x5b, 0x70, 0x3d, 0x71, 0xab, 0x96, 0xb9, 0x89, 0xfe, 0x32, 0x7c, 0xa2, 0x92, 0xaa, 0xc7, 0x88, 0x3a, 0x79, 0x9, 0xee, 0x1d, 0x11, 0xde, 0x29, 0x71, 0xf4, 0x9e, 0xe3, 0x35, 0x57, 0x44, 0x28, 0x71, 0xac, 0x10, 0x71, 0x10, 0xed, 0x19, 0x7e, 0x37, 0xad, 0xdf, 0x2a, 0x56, 0xa6, 0x47, 0xd4, 0xf7, 0x69, 0xa4, 0x67, 0x96, 0x52, 0x47, 0xa7, 0xbb, 0x5f, 0xe1, 0xeb, 0x2d, 0xce, 0x3b, 0xa7, 0x62, 0x82, 0xce, 0x91, 0x97, 0xed, 0x7a, 0x18, 0xbf, 0xb7, 0xf8, 0xa3, 0xd9, 0xa8, 0x9b, 0x1c, 0xcd, 0x78, 0xd2, 0xda, 0xf, 0x16, 0xd8, 0xf2, 0xe6, 0x97, 0xe3, 0xbe, 0xec, 0x78, 0xa9, 0xf0, 0x1e, 0x6, 0xe7, 0x67, 0xf9, 0xd5, 0x62, 0xe8, 0xc1, 0x62, 0xc5, 0x5e, 0xc, 0xf0, 0x30, 0x62, 0xfc, 0xa9, 0x46, 0x3, 0x48, 0x2d, 0xd3, 0x54, 0xbf, 0x9a, 0x82, 0x86, 0xca, 0x98, 0x1c, 0xf5, 0xea, 0xef, 0x30, 0x3c, 0x72, 0x44, 0x37, 0x53, 0xce, 0xfc, 0xb7, 0x87, 0x2c, 0xb3, 0xa, 0x4e, 0xdf, 0x3e, 0x9c, 0x58, 0xff, 0xf8, 0xff, 0x30, 0xae, 0xd0, 0x2e, 0x3a, 0x56, 0x65, 0x53, 0x9c, 0x7a, 0xf6, 0x97, 0x0, 0x7f, 0xd8, 0x6e, 0xe4, 0x20, 0x5c, 0x8a, 0x2f, 0x80, 0x49, 0xd2, 0xd9, 0xea, 0x3, 0xeb, 0x6d, 0x89, 0x94, 0x33, 0xd1, 0xd0, 0x4c, 0xd4, 0x6e, 0xc9, 0x26, 0x3d, 0xb4, 0xef, 0x8f, 0x80, 0xfe, 0xa8, 0xdf, 0x9c, 0x2f, 0x84, 0x6d, 0xf3, 0x4a, 0x1, 0x2e, 0xb, 0x4, 0x48, 0xfb, 0x36, 0x13, 0x88, 0x36, 0xec, 0x16, 0xe0, 0xdf, 0xee, 0x5, 0xc7, 0x37, 0x56, 0x3b, 0x47, 0xb5, 0xc0, 0x4f, 0x64, 0xbc, 0xe1, 0x42, 0x5f, 0xe8, 0xd3, 0xf2, 0xe1, 0x6f, 0x98, 0xb3, 0x79, 0x7c, 0x97, 0x48, 0x7c, 0xe, 0xd3, 0xba, 0x86, 0x7c, 0x83, 0xd0, 0xe6, 0x1c, 0xfd, 0x10, 0x14, 0x9c, 0x20, 0xbf, 0xd8, 0x73, 0x33, 0x9e, 0x7c, 0x97, 0x36, 0x50, 0x4d, 0x65, 0x4d, 0x4a, 0xfe, 0x13, 0xf, 0xaa, 0x35, 0xe3, 0x51, 0x10, 0xc2, 0x96, 0xd6, 0xdc, 0x84, 0x2b, 0x11, 0x46, 0xba, 0xdc, 0xfd, 0x62, 0xcc, 0x87, 0x6e, 0xb3, 0x66, 0x81, 0x2e, 0xe2, 0xc1, 0x50, 0x10, 0x3d, 0x13, 0xd7, 0xc2, 0x2c, 0xb, 0x8f, 0x2b, 0xc, 0x84, 0x9e, 0x85, 0x99, 0x33, 0xd8, 0x46, 0xf1, 0xde, 0x43, 0x20, 0x56, 0x97, 0x9a, 0xf2, 0xf3, 0x7a, 0xa3, 0xd9, 0x11, 0x8b, 0x9a, 0x43, 0x4b, 0x61, 0x9b, 0x43, 0x12, 0xa1, 0x8f, 0x16, 0x5d, 0x8b, 0x33, 0xbb, 0x87, 0x50, 0x8c, 0x92, 0x36, 0x8b, 0x1, 0x72, 0xd8, 0xc2, 0x3, 0x5d, 0xb8, 0xfc, 0x32, 0x8b, 0x81, 0x10, 0x49, 0x1f, 0x81, 0xd8, 0xef, 0x14, 0xb8, 0xd6, 0xf8, 0x4f, 0x49, 0x75, 0x1f, 0xee, 0x2c, 0x7d, 0xa1, 0xc0, 0x4f, 0xfb, 0x65, 0xaf, 0x2, 0x20, 0xc, 0xc4, 0xe0, 0xb5, 0xae, 0xfe, 0xc, 0x22, 0x88, 0x8b, 0xe, 0xda, 0xf7, 0x7f, 0x3e, 0xb5, 0x20, 0xd1, 0x7e, 0x48, 0x87, 0xe0, 0x66, 0x36, 0x15, 0x5a, 0x9b, 0xde, 0x25, 0xb9, 0xe5, 0x52, 0xb1, 0xf4, 0x9, 0xb, 0x94, 0x8f, 0x30, 0x25, 0x6e, 0x86, 0x51, 0x37, 0x86, 0x23, 0x80, 0x44, 0x2e, 0x50, 0x49, 0x86, 0x41, 0x22, 0xae, 0x11, 0xb, 0xa0, 0x6d, 0x70, 0x8d, 0x28, 0x24, 0x70, 0xb0, 0xe8, 0x99, 0x85, 0xc4, 0x52, 0x46, 0x8b, 0xa8, 0xe8, 0x51, 0xca, 0x6c, 0x26, 0x8, 0xb5, 0xba, 0x48, 0x40, 0x33, 0xb1, 0x9d, 0x85, 0x36, 0x4, 0x91, 0xcd, 0x76, 0xa6, 0xa0, 0x0, 0x73, 0xa6, 0x7d, 0x10, 0x14, 0x48, 0x5a, 0x11, 0x94, 0x34, 0x8a, 0xaa, 0xd0, 0xf4, 0x7d, 0x5e, 0x9f, 0x14, 0x55, 0xca, 0xba, 0xe8, 0xa, 0x7, 0xdb, 0x19, 0xb5, 0x90, 0x75, 0x1a, 0x8b, 0x10, 0xcf, 0x77, 0xf1, 0x69, 0xb0, 0x2b, 0x8d, 0x85, 0xd6, 0xc6, 0x3a, 0x80, 0xb5, 0x15, 0xcc, 0x55, 0xbf, 0xa5, 0xcd, 0x60, 0xae, 0xef, 0xf6, 0x2e, 0x74, 0xdb, 0xd6, 0xdd, 0xf7, 0x97, 0xbd, 0x7b, 0x1, 0xc3, 0x8d, 0x38, 0x76, 0xc8, 0x72, 0x63, 0x9e, 0x19, 0x34, 0xdd, 0xa8, 0xeb, 0x85, 0xed, 0xa9, 0x36, 0xe3, 0xbe, 0x39, 0x70, 0x98, 0x23, 0x8f, 0x39, 0x74, 0xfd, 0xf8, 0x12, 0x3b, 0xca, 0x8, 0xb2, 0x9d, 0xe6, 0x23, 0xa2, 0x27, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82, 0x00 };
+const unsigned char defaultDialogIcon7Name[] = { 0x71, 0x75, 0x65, 0x73, 0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x32, 0x78, 0x00 };
+const unsigned char defaultDialogIcon7Length[] = { 0x31, 0x35, 0x33, 0x38, 0x00 };
+const unsigned char defaultDialogIcon7Data[] = { 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x80, 0x0, 0x0, 0x0, 0x80, 0x8, 0x3, 0x0, 0x0, 0x0, 0xf4, 0xe0, 0x91, 0xf9, 0x0, 0x0, 0x0, 0x9c, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf8, 0x8d, 0x4c, 0xde, 0x0, 0x0, 0x0, 0x33, 0x74, 0x52, 0x4e, 0x53, 0x0, 0xfb, 0x42, 0x2, 0xa, 0x62, 0xb7, 0x82, 0xe6, 0x95, 0xe, 0x5, 0xb2, 0x19, 0x2b, 0xef, 0xe2, 0x3b, 0xd9, 0x4e, 0xc6, 0xf6, 0xbe, 0x55, 0x48, 0x91, 0x67, 0x33, 0x6c, 0x27, 0x23, 0xc2, 0xba, 0x20, 0x14, 0xd4, 0xa8, 0x89, 0x71, 0x38, 0xea, 0xd1, 0xcb, 0x8c, 0x7b, 0x52, 0x9c, 0xde, 0xa3, 0x88, 0x5c, 0x25, 0x3a, 0xec, 0xc2, 0x0, 0x0, 0x4, 0xe2, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0xec, 0x97, 0xdb, 0x76, 0xb2, 0x30, 0x10, 0x85, 0x87, 0x70, 0x52, 0x11, 0x1, 0x1, 0x6b, 0x55, 0xea, 0x59, 0xeb, 0xa1, 0x6a, 0x3b, 0xef, 0xff, 0x6e, 0xff, 0xc5, 0xbf, 0x96, 0x24, 0x30, 0x61, 0x0, 0x6d, 0xaf, 0xfc, 0x6e, 0x61, 0x85, 0x64, 0xcf, 0xec, 0xd9, 0x1, 0x5e, 0xbc, 0x78, 0xf1, 0xe2, 0x45, 0x7b, 0x2c, 0x3f, 0x9b, 0x8a, 0x38, 0x16, 0xd3, 0xcc, 0xb7, 0xe0, 0x6f, 0xe9, 0x89, 0x59, 0x77, 0x11, 0xa2, 0x44, 0xb8, 0xe8, 0xce, 0x44, 0xf, 0xfe, 0x2, 0x4f, 0xb8, 0x89, 0x81, 0x24, 0x46, 0xe2, 0xa, 0xf, 0x7e, 0x15, 0x73, 0xbc, 0x49, 0xb1, 0x92, 0x74, 0x33, 0x36, 0xe1, 0xb7, 0x18, 0x9c, 0x3a, 0x58, 0x83, 0xce, 0x69, 0x0, 0xbf, 0x41, 0xe4, 0x60, 0x6d, 0x9c, 0x8, 0x9e, 0x8d, 0x18, 0x61, 0x23, 0x46, 0xe2, 0xb9, 0xe2, 0x8f, 0xb0, 0x31, 0xa3, 0xe7, 0x15, 0xc2, 0xda, 0x1a, 0xd8, 0x2, 0x63, 0x6b, 0xc1, 0x53, 0x88, 0x43, 0x6c, 0x49, 0x18, 0x3f, 0xc3, 0x79, 0x27, 0x7c, 0x80, 0xed, 0xc3, 0x9e, 0xec, 0xf5, 0xb5, 0xa, 0x87, 0xc7, 0x7e, 0xf7, 0x6c, 0xdb, 0xe7, 0x6e, 0xff, 0x18, 0x6a, 0x6b, 0xd4, 0x7f, 0x70, 0x3c, 0x7e, 0xac, 0x91, 0xe2, 0xe0, 0xee, 0x7d, 0x53, 0xd1, 0xc9, 0xdf, 0xbb, 0x7, 0xa4, 0x58, 0x7f, 0x3c, 0x64, 0xbe, 0x4f, 0xe2, 0xe4, 0xf3, 0xdd, 0x12, 0x48, 0x96, 0xbb, 0x39, 0xa1, 0xc4, 0xa7, 0x80, 0xd6, 0x4c, 0xca, 0xeb, 0x39, 0xf6, 0xa, 0x2a, 0x58, 0xd9, 0x4e, 0x79, 0xc7, 0x93, 0xb6, 0xb1, 0xd3, 0xc5, 0x22, 0x49, 0x4, 0x2c, 0x51, 0x82, 0x45, 0xde, 0xbd, 0x56, 0xdf, 0x2f, 0x9d, 0x65, 0xf8, 0x5, 0xb5, 0xf8, 0x1a, 0x96, 0x74, 0x6b, 0xb3, 0x83, 0xe2, 0xf9, 0x3b, 0x93, 0xda, 0xab, 0x78, 0x93, 0x4e, 0x51, 0x83, 0x16, 0xf5, 0x2f, 0x14, 0xd2, 0xb5, 0xa0, 0x1, 0x96, 0x6b, 0xa0, 0x42, 0xe3, 0x3e, 0x10, 0xea, 0x2, 0x81, 0x68, 0xbc, 0x40, 0xa0, 0x1e, 0x40, 0x34, 0xf4, 0xbf, 0xea, 0xbf, 0x61, 0xb, 0x33, 0x7f, 0xc, 0x55, 0x37, 0x2e, 0x1b, 0xcd, 0xbf, 0xb5, 0xda, 0x43, 0xbd, 0x56, 0x43, 0xd4, 0x51, 0x27, 0x52, 0x83, 0x45, 0x4c, 0x75, 0xfe, 0x9e, 0x4c, 0x8d, 0xe7, 0x6f, 0xa3, 0x61, 0x9a, 0x5e, 0xe7, 0x9b, 0x99, 0x4f, 0x2f, 0xf3, 0xae, 0x4e, 0xe5, 0xfa, 0xb9, 0xb0, 0x55, 0xaa, 0x67, 0x93, 0x8b, 0xdb, 0xca, 0xd4, 0x3b, 0xce, 0x48, 0x8b, 0xd8, 0x86, 0x92, 0x4c, 0xb5, 0xf3, 0x17, 0x65, 0xc8, 0xef, 0x8f, 0x4b, 0x19, 0x71, 0x7d, 0x23, 0x77, 0x80, 0x32, 0x71, 0x4d, 0xb, 0x85, 0x94, 0x83, 0xf9, 0x88, 0x9c, 0x53, 0x85, 0x50, 0xaa, 0x10, 0x5a, 0xcd, 0xb, 0xe0, 0x98, 0xb5, 0x23, 0x12, 0xc3, 0x29, 0x51, 0x2a, 0xa5, 0x13, 0xbf, 0xa1, 0x6, 0x3, 0x43, 0xf6, 0x1f, 0xd1, 0xba, 0xd3, 0x0, 0x35, 0xa4, 0x82, 0x50, 0x4b, 0x76, 0xa3, 0x31, 0x0, 0x9e, 0x11, 0xe6, 0x4, 0x84, 0xff, 0xfd, 0xe, 0x6a, 0x9, 0x32, 0x42, 0x2f, 0x79, 0xbf, 0x23, 0x60, 0x11, 0xcc, 0xf8, 0xb2, 0x8e, 0x58, 0xc1, 0x70, 0xc5, 0xc, 0x55, 0xd1, 0x48, 0x0, 0x97, 0xc9, 0x28, 0x82, 0xd, 0x94, 0x71, 0x9b, 0x48, 0x10, 0xc9, 0xf9, 0x47, 0x34, 0x6d, 0x66, 0x60, 0x35, 0x7b, 0x42, 0x34, 0x79, 0xae, 0x47, 0x50, 0x8d, 0xc3, 0x24, 0x58, 0xc1, 0x80, 0x69, 0x92, 0xa4, 0x5, 0x33, 0x42, 0x99, 0x99, 0x6c, 0x2b, 0xc6, 0x2, 0x72, 0x3d, 0x3d, 0xc2, 0x1, 0x6a, 0xca, 0xf, 0x4c, 0x0, 0x73, 0x20, 0x79, 0x9d, 0xae, 0xb2, 0x27, 0x3b, 0xa1, 0xda, 0x8, 0x27, 0xcc, 0xa1, 0xee, 0x3f, 0xdf, 0xf2, 0xec, 0xbb, 0x7f, 0x4a, 0x5c, 0x31, 0xe7, 0x42, 0xdd, 0x91, 0xe4, 0x64, 0xa9, 0x4c, 0x21, 0xc9, 0x62, 0x9, 0x10, 0x48, 0x47, 0x9, 0x7c, 0xc9, 0x9a, 0x81, 0xd4, 0x39, 0x54, 0xe6, 0x24, 0xc4, 0x73, 0x8a, 0x31, 0xd3, 0x2d, 0x19, 0xe6, 0xfc, 0x80, 0xc4, 0x8f, 0xdc, 0x86, 0x4c, 0x6f, 0x8f, 0x41, 0xcf, 0x86, 0x69, 0x96, 0x37, 0xed, 0xf3, 0x5, 0x73, 0xfb, 0x72, 0x64, 0xa7, 0x6a, 0xf1, 0x52, 0x26, 0x4, 0x77, 0x78, 0x67, 0xa7, 0x7d, 0xe2, 0x32, 0xb1, 0x98, 0x7a, 0x75, 0xa6, 0xa0, 0xb1, 0x62, 0x7a, 0x34, 0xd2, 0x6a, 0x7c, 0x1, 0x82, 0x95, 0x51, 0x67, 0x1a, 0xba, 0xb2, 0x9d, 0x29, 0x6e, 0xf9, 0x6, 0xad, 0x42, 0xe6, 0x48, 0x37, 0x1f, 0xa0, 0x98, 0x93, 0x12, 0xe9, 0x7b, 0x75, 0xc7, 0xec, 0x70, 0xad, 0x1f, 0x20, 0x1b, 0x60, 0xaa, 0x97, 0x80, 0x86, 0x9e, 0x24, 0xd3, 0x92, 0x76, 0x89, 0x56, 0x67, 0x9b, 0xfb, 0x9, 0x59, 0xa2, 0xa4, 0x1e, 0xdf, 0x2, 0x7, 0xc8, 0xa1, 0x9a, 0x3d, 0x58, 0xea, 0x33, 0xea, 0xc, 0x24, 0x7, 0xbe, 0x9, 0x66, 0x7c, 0x99, 0xfc, 0xff, 0xcb, 0x4, 0x31, 0xa8, 0x64, 0xa9, 0xb4, 0x3c, 0xdb, 0x60, 0x33, 0xfe, 0x6f, 0x70, 0xaf, 0x75, 0xea, 0x79, 0x1e, 0xac, 0x2f, 0xc5, 0xf3, 0x9b, 0x47, 0x5e, 0xe0, 0x3d, 0xde, 0xe9, 0x6a, 0xf5, 0xbd, 0xe3, 0x43, 0x13, 0xac, 0x1b, 0xe6, 0x2c, 0x74, 0xe2, 0xf1, 0xaf, 0x84, 0xf9, 0x29, 0x4c, 0x68, 0x40, 0x74, 0x45, 0xe4, 0xb, 0x6c, 0xe6, 0x2d, 0x1e, 0x6a, 0xce, 0x81, 0xc4, 0x1b, 0xc, 0x56, 0xb4, 0xbb, 0xd, 0x51, 0x66, 0x1, 0x3a, 0xa4, 0xa0, 0xb3, 0x38, 0x8d, 0x8e, 0x50, 0x8b, 0xde, 0xc5, 0xc0, 0x22, 0x53, 0xd0, 0x71, 0xe4, 0x2a, 0x9c, 0xa9, 0xc3, 0x8c, 0xa7, 0x77, 0xe5, 0xef, 0x84, 0xf4, 0x65, 0x2a, 0x3, 0x8a, 0xa9, 0xda, 0xa6, 0x3c, 0x17, 0x2c, 0x61, 0x64, 0xa0, 0xa5, 0xcb, 0xc9, 0x24, 0x94, 0x59, 0xc2, 0x63, 0x95, 0xf5, 0x4f, 0xab, 0xb2, 0xfe, 0xcc, 0x35, 0x6a, 0xac, 0x64, 0x31, 0x4f, 0x54, 0xf1, 0x67, 0xc4, 0x24, 0x72, 0xfc, 0x94, 0xd, 0xbc, 0x61, 0x81, 0xe0, 0x5f, 0xfb, 0x76, 0xb3, 0x9a, 0x30, 0x14, 0x44, 0x1, 0xb8, 0x12, 0x17, 0x37, 0x20, 0x95, 0x2e, 0xa, 0xa6, 0x75, 0xd1, 0xa, 0x5, 0x37, 0x95, 0xd6, 0xf7, 0x7f, 0xb8, 0x62, 0x11, 0x5, 0xaf, 0xf1, 0x53, 0xc7, 0x9f, 0x1b, 0xc9, 0x59, 0x67, 0x31, 0x9a, 0xcc, 0xdf, 0x39, 0x67, 0x5e, 0x9e, 0x2, 0x1, 0xe8, 0x15, 0x38, 0x80, 0x71, 0x5b, 0xf9, 0xf4, 0x2b, 0xf0, 0x47, 0xe8, 0x0, 0x6, 0x8b, 0x19, 0x9e, 0xc7, 0x47, 0x88, 0x34, 0x44, 0x0, 0xaf, 0x3f, 0x6d, 0xf9, 0xef, 0x34, 0x74, 0x21, 0x72, 0x0, 0xd, 0x8, 0x28, 0x14, 0x22, 0x95, 0x62, 0x7, 0x90, 0xd1, 0x33, 0x2a, 0xc5, 0x6e, 0x46, 0xa1, 0x0, 0xdc, 0x8c, 0xdc, 0x8e, 0x43, 0x1, 0xb8, 0x1d, 0x7b, 0x20, 0x9, 0x5, 0xe0, 0x81, 0xc4, 0x23, 0x59, 0x2c, 0x0, 0x8f, 0x64, 0x1e, 0x4a, 0x8d, 0xef, 0x3, 0x8b, 0xb4, 0x87, 0x52, 0x8f, 0xe5, 0xc4, 0x33, 0xf2, 0x1a, 0x63, 0x39, 0x17, 0x13, 0xa2, 0x1a, 0x6f, 0x8a, 0x70, 0x96, 0x34, 0x5e, 0x4c, 0xbc, 0x9a, 0x19, 0x6f, 0xe8, 0x5d, 0x58, 0xcd, 0xb8, 0x9c, 0x1a, 0x35, 0x3a, 0x7, 0x96, 0x53, 0xae, 0xe7, 0xc6, 0x64, 0x94, 0xd2, 0x68, 0x82, 0x87, 0xb0, 0x9e, 0x83, 0xa0, 0x8, 0x40, 0x4, 0x85, 0x29, 0x9a, 0x10, 0x4c, 0xd1, 0x98, 0xa4, 0x8a, 0xc1, 0x24, 0x95, 0x69, 0xba, 0x18, 0x4c, 0xd3, 0x99, 0xa8, 0xc, 0xc1, 0x44, 0xa5, 0xa9, 0x5a, 0x61, 0xb6, 0xac, 0xeb, 0x25, 0x12, 0x16, 0x54, 0x2d, 0xc8, 0x6a, 0x64, 0x61, 0xfa, 0x7f, 0x4c, 0x79, 0x38, 0x9c, 0x83, 0x45, 0x4, 0x5d, 0xdf, 0x8a, 0xf7, 0xc1, 0xba, 0x68, 0x61, 0x1e, 0x4, 0x5d, 0xf, 0xc1, 0x2, 0xfd, 0xd, 0xbd, 0x53, 0x82, 0x85, 0x25, 0x1b, 0x8c, 0x38, 0x18, 0xa0, 0x2c, 0xd9, 0x58, 0xb4, 0x42, 0xd5, 0x42, 0x6d, 0xb1, 0x68, 0x65, 0xd9, 0xe, 0x29, 0x8b, 0xd4, 0xa2, 0x6c, 0x67, 0xe1, 0x32, 0x36, 0xf, 0x58, 0xb8, 0xb4, 0x74, 0x8b, 0x79, 0x20, 0x2b, 0x18, 0x90, 0x6e, 0x3, 0xe2, 0x75, 0x86, 0x45, 0xc6, 0x9a, 0x42, 0xbc, 0x3e, 0x53, 0xbe, 0x6f, 0xaa, 0xd6, 0xff, 0x6a, 0x35, 0xf, 0x64, 0xbf, 0xb, 0xf2, 0xfd, 0xed, 0xc, 0xc, 0x1f, 0x3b, 0x6, 0x86, 0x2e, 0x59, 0x38, 0xee, 0x6f, 0x62, 0xb9, 0xbf, 0x8d, 0x67, 0x8f, 0x91, 0x69, 0x7a, 0xbc, 0x91, 0x69, 0x3a, 0x87, 0x91, 0xe9, 0x6, 0x56, 0x2e, 0x27, 0x80, 0x23, 0x68, 0x2e, 0x67, 0x66, 0xeb, 0xa6, 0x9d, 0xaf, 0x0, 0x43, 0xe3, 0x45, 0x2c, 0x9d, 0x9f, 0x57, 0x33, 0xb5, 0xa6, 0xad, 0xa9, 0x35, 0xc1, 0xd4, 0x1a, 0x41, 0xf5, 0x15, 0xb3, 0xf5, 0x76, 0xdf, 0xd8, 0x1c, 0xb0, 0x76, 0xff, 0xae, 0x8a, 0xe7, 0x43, 0x98, 0xdb, 0xb, 0xb0, 0xf7, 0x17, 0x70, 0xe0, 0x50, 0xc0, 0x89, 0x47, 0x1, 0x47, 0x2e, 0x5, 0x9c, 0xf9, 0xac, 0x31, 0xdc, 0x7f, 0xe8, 0x74, 0x42, 0xd6, 0x75, 0xfd, 0xd4, 0xab, 0x47, 0x8f, 0x1e, 0x3d, 0x1e, 0xa, 0x7f, 0x3b, 0x1f, 0x29, 0xf, 0xbf, 0x29, 0x8c, 0x32, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82, 0x00 };
+const unsigned char defaultDialogIcon8Name[] = { 0x77, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x2d, 0x64, 0x61, 0x72, 0x6b, 0x00 };
+const unsigned char defaultDialogIcon8Length[] = { 0x38, 0x33, 0x30, 0x00 };
+const unsigned char defaultDialogIcon8Data[] = { 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x40, 0x0, 0x0, 0x0, 0x40, 0x8, 0x3, 0x0, 0x0, 0x0, 0x9d, 0xb7, 0x81, 0xec, 0x0, 0x0, 0x0, 0x78, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc6, 0xa8, 0xe4, 0xac, 0x0, 0x0, 0x0, 0x27, 0x74, 0x52, 0x4e, 0x53, 0x0, 0x3, 0xfb, 0xa5, 0x7e, 0xc9, 0x8e, 0xeb, 0xb2, 0x1c, 0x13, 0xc, 0x7b, 0xa4, 0x43, 0x92, 0xf6, 0xe1, 0xa0, 0x77, 0x47, 0x25, 0x8, 0xc5, 0xf2, 0xdc, 0xd6, 0xd4, 0x88, 0x6b, 0x51, 0x29, 0x27, 0xe, 0xbe, 0x37, 0x36, 0xbf, 0x58, 0xbe, 0xe, 0x1c, 0x70, 0x0, 0x0, 0x2, 0x4e, 0x49, 0x44, 0x41, 0x54, 0x58, 0xc3, 0xdc, 0x54, 0x6b, 0x8f, 0x82, 0x40, 0xc, 0x64, 0x91, 0xe5, 0xa5, 0x82, 0xf2, 0x46, 0x5e, 0xea, 0x99, 0xf4, 0xff, 0xff, 0xc3, 0x4b, 0xbb, 0x1e, 0x50, 0xea, 0x5, 0x3c, 0xbf, 0x5d, 0xa3, 0x89, 0x3b, 0x9d, 0x19, 0xda, 0x6e, 0xd1, 0xfa, 0xdf, 0xa1, 0xc6, 0xf8, 0x93, 0x58, 0x9c, 0xdf, 0x9, 0x62, 0x7, 0x59, 0xd7, 0xc6, 0x49, 0x12, 0xb7, 0x5d, 0x16, 0x10, 0xf8, 0x8e, 0x5c, 0x45, 0xae, 0x3e, 0xc1, 0x18, 0x27, 0xed, 0x46, 0x88, 0x6e, 0x95, 0x87, 0x69, 0x43, 0x3a, 0xfb, 0x19, 0x74, 0x68, 0xd2, 0x90, 0x92, 0xeb, 0xfa, 0xbd, 0xe3, 0x91, 0x78, 0x74, 0xf8, 0x39, 0x79, 0xce, 0x7e, 0xcd, 0x1, 0xf3, 0x7d, 0x4d, 0x7c, 0xfa, 0x9a, 0x98, 0xce, 0x75, 0x2f, 0x8a, 0x10, 0x7a, 0x17, 0x0, 0x95, 0xa4, 0xae, 0xce, 0xda, 0xf7, 0xf5, 0xb9, 0x2, 0x18, 0x41, 0x97, 0x3b, 0xc8, 0xf2, 0x7d, 0x7a, 0x12, 0x7e, 0xca, 0xc3, 0x23, 0x2c, 0x70, 0x72, 0x45, 0xf8, 0x38, 0x94, 0x4, 0x62, 0xce, 0x9f, 0xb5, 0x21, 0xf5, 0xd7, 0xb, 0xd1, 0xb0, 0xdd, 0x9c, 0xe7, 0x72, 0x1c, 0xc, 0xe5, 0x2e, 0xd7, 0xc9, 0x41, 0xe8, 0x3d, 0xc3, 0xb1, 0xdd, 0x80, 0xed, 0xe, 0xfd, 0xa, 0x5c, 0xdb, 0x64, 0xbd, 0xd1, 0x41, 0xd4, 0xff, 0x7c, 0x7e, 0x39, 0xbc, 0xde, 0xc4, 0x41, 0x3f, 0x6b, 0xf8, 0xad, 0xb, 0xdf, 0x8c, 0xee, 0xa8, 0x26, 0x39, 0xb7, 0x50, 0x47, 0x33, 0x4e, 0xff, 0x75, 0x1, 0xae, 0xd1, 0x3b, 0x6c, 0xce, 0x93, 0x15, 0xc1, 0x8e, 0x71, 0x70, 0x2d, 0x25, 0xf5, 0xbd, 0xa9, 0xcf, 0x61, 0x1a, 0x51, 0x84, 0x63, 0x58, 0xbd, 0x74, 0xd8, 0xd7, 0x80, 0x43, 0x3a, 0xf2, 0x8c, 0xca, 0x32, 0x7e, 0xb6, 0x8e, 0x44, 0xab, 0xf7, 0xa2, 0x0, 0x87, 0x12, 0x5a, 0x31, 0x83, 0xdb, 0x1d, 0xe0, 0x7e, 0x63, 0x3c, 0xa5, 0x89, 0xe8, 0x2c, 0x4b, 0x8, 0xcd, 0xd, 0xe, 0x88, 0x4f, 0xec, 0x3, 0xae, 0xce, 0x81, 0x63, 0x83, 0xb9, 0xcb, 0x70, 0x51, 0x40, 0xa, 0xb6, 0x18, 0xe, 0xd5, 0x8b, 0x5d, 0x71, 0x30, 0x26, 0x6a, 0xba, 0xe8, 0xb5, 0x41, 0xaa, 0x17, 0x2c, 0xb8, 0x3b, 0x44, 0x77, 0xb, 0x30, 0xf0, 0x10, 0x6d, 0x38, 0x18, 0x1, 0x4c, 0x8d, 0x49, 0x3, 0x39, 0x2e, 0x80, 0x8, 0x61, 0xbe, 0x3, 0x76, 0xbe, 0xcd, 0x20, 0xb7, 0xe5, 0x2e, 0x68, 0x64, 0x96, 0xd3, 0x59, 0x18, 0xb0, 0x28, 0x11, 0xd6, 0x73, 0x24, 0x38, 0x1, 0xf0, 0x71, 0x4b, 0x3, 0x7e, 0x39, 0x0, 0xa7, 0x60, 0x86, 0x64, 0x80, 0xf1, 0xd8, 0x6a, 0xf0, 0x45, 0xf4, 0x8c, 0x70, 0x83, 0x74, 0x68, 0x59, 0x85, 0x5b, 0x5b, 0x8, 0x2b, 0x2c, 0xb8, 0x9b, 0x19, 0xb4, 0x48, 0x3c, 0x17, 0x5b, 0xd, 0x8a, 0x33, 0xe2, 0xed, 0xcc, 0x20, 0xa6, 0xa9, 0xa8, 0xad, 0x6, 0x8a, 0x66, 0x1e, 0xcf, 0xc, 0x12, 0x4, 0x7c, 0x6b, 0xab, 0x81, 0xe5, 0x23, 0x9e, 0x7c, 0x6c, 0xf0, 0x71, 0xb, 0xeb, 0x43, 0x94, 0x2f, 0x93, 0x1c, 0xa2, 0xbc, 0x46, 0xf9, 0x3a, 0xaf, 0x5c, 0xa3, 0x5c, 0x24, 0xf9, 0x87, 0xb2, 0xb2, 0x48, 0x72, 0x95, 0x27, 0x72, 0xf4, 0xdd, 0x7d, 0xb9, 0xa3, 0x0, 0xc, 0xc3, 0x30, 0x74, 0xea, 0x9a, 0xe6, 0x73, 0x84, 0x90, 0xf8, 0xfe, 0x37, 0x6c, 0x31, 0x18, 0xf, 0xa2, 0x8, 0xaa, 0x2d, 0x86, 0x40, 0x8, 0x64, 0x31, 0xb6, 0xf4, 0x54, 0xf2, 0xd, 0x47, 0x19, 0x97, 0x9, 0x55, 0xd4, 0xf, 0x5b, 0x26, 0x5c, 0xe7, 0xec, 0x97, 0x77, 0x96, 0xac, 0x33, 0x8, 0x4a, 0xd6, 0x68, 0x6d, 0xc4, 0x1d, 0x5, 0x85, 0x4b, 0xda, 0xb6, 0xb7, 0xf6, 0xa7, 0xa4, 0x71, 0x51, 0xed, 0x56, 0xab, 0x75, 0x22, 0xaa, 0x8a, 0xac, 0x73, 0x63, 0x59, 0x66, 0x8b, 0x18, 0xb, 0xb1, 0xb6, 0x52, 0x88, 0xb5, 0xc9, 0xe6, 0xaa, 0xdb, 0xbb, 0xe, 0x18, 0x88, 0x38, 0xd7, 0x2f, 0xc4, 0xe1, 0x90, 0x75, 0x7, 0x64, 0xf9, 0xc4, 0xb, 0x98, 0x17, 0xff, 0x39, 0x68, 0xce, 0x0, 0xcd, 0x9, 0xa0, 0xa9, 0xa1, 0xae, 0xa, 0xdb, 0x22, 0xee, 0xab, 0x81, 0x43, 0x8c, 0x3c, 0x62, 0xe8, 0x12, 0x63, 0x9f, 0x16, 0x3c, 0x8f, 0xae, 0x7, 0x37, 0xe7, 0x62, 0x42, 0xa9, 0x5c, 0xc2, 0xf9, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82, 0x00 };
+const unsigned char defaultDialogIcon9Name[] = { 0x77, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x2d, 0x64, 0x61, 0x72, 0x6b, 0x32, 0x78, 0x00 };
+const unsigned char defaultDialogIcon9Length[] = { 0x31, 0x32, 0x37, 0x34, 0x00 };
+const unsigned char defaultDialogIcon9Data[] = { 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x80, 0x0, 0x0, 0x0, 0x80, 0x8, 0x3, 0x0, 0x0, 0x0, 0xf4, 0xe0, 0x91, 0xf9, 0x0, 0x0, 0x0, 0x96, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x25, 0xc5, 0xa8, 0x0, 0x0, 0x0, 0x31, 0x74, 0x52, 0x4e, 0x53, 0x0, 0x55, 0xfb, 0x3, 0xe3, 0xc, 0x43, 0x92, 0x8a, 0xd7, 0xb7, 0x82, 0x62, 0x40, 0x19, 0x48, 0x4e, 0x2b, 0xee, 0xe7, 0x39, 0xbf, 0x21, 0x97, 0x67, 0xb4, 0x33, 0xd0, 0x6c, 0x9, 0xcb, 0xf, 0xc5, 0xb1, 0xf6, 0xc2, 0xbc, 0xa8, 0x71, 0x26, 0x25, 0x14, 0x7, 0xc6, 0x3b, 0x7c, 0x5d, 0x11, 0x7b, 0x95, 0x98, 0x75, 0x67, 0x0, 0x0, 0x3, 0xe2, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0xec, 0x96, 0xd9, 0x8e, 0xb3, 0x30, 0xc, 0x85, 0x5d, 0x2, 0x94, 0xb2, 0xb7, 0x65, 0x69, 0xe9, 0xbe, 0x4f, 0xb7, 0x91, 0xf2, 0xfe, 0x2f, 0xf7, 0x4b, 0xbf, 0x46, 0xc2, 0x50, 0x1a, 0x13, 0x12, 0x46, 0x73, 0xd1, 0xef, 0xda, 0xa2, 0x27, 0x3e, 0x3e, 0x76, 0xe1, 0xc3, 0x87, 0xf, 0x1f, 0x3e, 0x74, 0x67, 0x15, 0x5e, 0xa, 0x3b, 0x8e, 0xed, 0xe2, 0x12, 0xae, 0xe0, 0x77, 0xb1, 0xec, 0x65, 0x7e, 0x34, 0x39, 0xc2, 0x3c, 0xe6, 0x4b, 0xdb, 0x82, 0xdf, 0xe0, 0x16, 0x78, 0x77, 0x83, 0x37, 0x62, 0xdc, 0xbd, 0xe0, 0x6, 0xbd, 0xc2, 0xa2, 0xd3, 0x9e, 0xb, 0xd9, 0x9f, 0x22, 0x6, 0x7d, 0x31, 0x76, 0xa6, 0xbc, 0x5, 0x53, 0x67, 0xc, 0x7d, 0xf0, 0x70, 0x79, 0x6b, 0xdc, 0x4, 0x74, 0x63, 0xa7, 0x5c, 0x8a, 0xd4, 0xd6, 0xdb, 0xfc, 0x94, 0x4b, 0x93, 0xea, 0x33, 0xc2, 0x72, 0xc, 0xde, 0x1, 0xc3, 0xd1, 0x94, 0xcb, 0xd8, 0xe4, 0x1d, 0x31, 0x63, 0x50, 0x87, 0x39, 0x5c, 0x1, 0x87, 0x29, 0xb7, 0x7f, 0xfe, 0xb6, 0xc3, 0xe6, 0x7a, 0x97, 0x3f, 0x7d, 0xff, 0x99, 0xef, 0xd6, 0xe6, 0x5b, 0x8f, 0xe6, 0x8a, 0x36, 0x64, 0x23, 0xde, 0xc4, 0xc2, 0x4b, 0x42, 0x6, 0x8, 0x16, 0x26, 0xde, 0x82, 0x37, 0x31, 0xca, 0x40, 0x81, 0x60, 0xd2, 0xf0, 0xf2, 0xc3, 0x39, 0x7b, 0xa3, 0xf6, 0x7c, 0x68, 0xe8, 0xc4, 0x24, 0x80, 0xce, 0xcc, 0x5e, 0xbf, 0xe7, 0xfa, 0x57, 0x10, 0x70, 0xf5, 0xdd, 0x57, 0xc5, 0x33, 0xe8, 0x6, 0x1b, 0xf2, 0x3a, 0xdb, 0x4, 0x48, 0x1e, 0x5b, 0x5e, 0x67, 0xc8, 0x3a, 0xfd, 0xfe, 0xfc, 0xc5, 0xce, 0x96, 0xa9, 0x1a, 0x8c, 0x5e, 0x46, 0xb1, 0x8b, 0x82, 0xfa, 0xfb, 0xa7, 0x33, 0xd6, 0x5a, 0xfb, 0x6c, 0x5a, 0xef, 0x41, 0x7, 0xff, 0x6b, 0x46, 0x7a, 0x96, 0x54, 0x7a, 0xbd, 0xda, 0xf8, 0x48, 0xcf, 0x41, 0x60, 0x54, 0x47, 0xd9, 0x6, 0x49, 0xec, 0x6a, 0x80, 0x8c, 0x40, 0x32, 0xff, 0x93, 0xaa, 0xfb, 0x5f, 0x20, 0xcd, 0xd7, 0xa8, 0xfa, 0x84, 0x4c, 0xaa, 0x83, 0xa3, 0x6a, 0xf6, 0x36, 0xd0, 0x81, 0x8d, 0x5b, 0x7d, 0x84, 0xd5, 0x39, 0x0, 0xe, 0x53, 0xcb, 0xb1, 0x7c, 0x14, 0x9c, 0x8a, 0x7b, 0x3e, 0x74, 0xc6, 0x37, 0x2a, 0xf, 0x81, 0x96, 0xc4, 0x1c, 0xe3, 0x83, 0x2, 0x3e, 0xc7, 0xc4, 0x2d, 0x7, 0xc0, 0x14, 0x24, 0x58, 0x69, 0x9b, 0x98, 0x2b, 0x79, 0x3, 0x5c, 0x6, 0x4a, 0x30, 0x57, 0xda, 0x84, 0x31, 0xf6, 0x6d, 0xb4, 0x11, 0xf, 0xfa, 0xf7, 0x70, 0xf8, 0x4d, 0x94, 0xe0, 0x40, 0x19, 0x63, 0xa0, 0x49, 0x71, 0x78, 0xc5, 0xf9, 0x8f, 0xfe, 0x9b, 0x65, 0x46, 0xe2, 0x7d, 0x80, 0x57, 0x4a, 0xa, 0x24, 0x36, 0x16, 0x6c, 0x83, 0x88, 0xc2, 0xf8, 0x29, 0x2b, 0xc4, 0x5f, 0xc4, 0x2d, 0xb5, 0xa5, 0x1a, 0xe0, 0x81, 0x90, 0x5, 0xff, 0x61, 0xd, 0x42, 0x3c, 0x99, 0x16, 0x3c, 0xf0, 0xfd, 0xb3, 0x40, 0x44, 0x58, 0x56, 0x86, 0xe2, 0x58, 0xe1, 0xdb, 0x98, 0x80, 0x18, 0xb7, 0xfd, 0x5, 0x8b, 0xca, 0xca, 0x8, 0x84, 0x2c, 0x71, 0xac, 0x88, 0x8, 0xe0, 0x4, 0x10, 0x9, 0x1c, 0x94, 0xa5, 0x3, 0x22, 0x8b, 0x38, 0x9, 0xe3, 0xd6, 0x3b, 0x60, 0x0, 0x84, 0x0, 0xe9, 0x52, 0x7a, 0x17, 0x30, 0xe4, 0xd6, 0x16, 0xf4, 0x9, 0x80, 0x3b, 0x9a, 0x2c, 0xd6, 0xce, 0x56, 0x9e, 0xe8, 0x14, 0xf0, 0xe0, 0xed, 0x6, 0xe6, 0x44, 0xd, 0xb, 0x2d, 0x80, 0x1e, 0xee, 0x13, 0xbc, 0xe5, 0xb6, 0xa7, 0x8e, 0x20, 0x2d, 0x80, 0x3e, 0x8b, 0xfb, 0x1b, 0xbc, 0x23, 0x40, 0x4b, 0xf0, 0xaa, 0x57, 0xc0, 0x15, 0xad, 0xc3, 0xa0, 0xcd, 0xca, 0x3a, 0x80, 0x5e, 0x1, 0x70, 0xa8, 0x2c, 0x58, 0x7a, 0x56, 0xcf, 0xba, 0x5, 0x9c, 0x5b, 0xe4, 0xcb, 0x42, 0x6d, 0xca, 0x74, 0xb, 0xc8, 0x90, 0xbd, 0x16, 0x7d, 0x8, 0x17, 0xa0, 0x5b, 0x0, 0x2c, 0xe8, 0x93, 0xb8, 0x44, 0x36, 0x29, 0x8, 0xa0, 0x7, 0x6c, 0x9, 0xcd, 0xe4, 0x68, 0xb, 0xe9, 0x17, 0x90, 0xd0, 0xff, 0x33, 0x8f, 0xe8, 0xbe, 0x2a, 0x8, 0xa0, 0xaf, 0xf7, 0x11, 0x9a, 0x31, 0xcb, 0x31, 0x61, 0xfa, 0x5, 0xb0, 0x72, 0xc4, 0x4d, 0x68, 0x64, 0xc5, 0x51, 0x85, 0x8a, 0x0, 0xf2, 0x7d, 0x7c, 0x45, 0xf5, 0x68, 0xdd, 0x87, 0x80, 0x35, 0xe5, 0xf0, 0xa5, 0x2c, 0xd8, 0xf5, 0x21, 0x60, 0x57, 0xd6, 0x5f, 0xa0, 0x89, 0xa2, 0x2c, 0xc8, 0x95, 0x4, 0xd0, 0x21, 0x2b, 0xa8, 0x53, 0xf4, 0xec, 0x43, 0xc0, 0x93, 0x3a, 0x47, 0x31, 0xba, 0xc5, 0x4a, 0x2, 0xe8, 0x8b, 0x1c, 0xff, 0x4d, 0x1, 0xff, 0xda, 0x37, 0x83, 0x15, 0x4, 0xa1, 0x28, 0x88, 0x1a, 0x12, 0x6e, 0x14, 0x34, 0x5d, 0x24, 0x19, 0xd8, 0x3a, 0x41, 0xff, 0xff, 0xeb, 0xc2, 0xa0, 0x20, 0x31, 0x4f, 0x3a, 0xd2, 0x7d, 0xca, 0x9b, 0xb5, 0xbb, 0xd2, 0x7b, 0x67, 0xee, 0x19, 0xf3, 0x9f, 0xc0, 0xfc, 0x4f, 0x68, 0xfe, 0x1a, 0x9a, 0x7f, 0x88, 0xe0, 0x53, 0xc, 0xd6, 0x4c, 0xf8, 0x14, 0xf3, 0x30, 0x62, 0x73, 0x2a, 0xd, 0x23, 0x1e, 0xc7, 0x6c, 0xcf, 0x85, 0x71, 0xcc, 0xb, 0x9, 0x7, 0x14, 0x59, 0x20, 0x2c, 0x24, 0xb0, 0x92, 0x9, 0x11, 0xd, 0xac, 0x64, 0xca, 0x52, 0xca, 0x21, 0x15, 0x2f, 0xa5, 0xbc, 0x96, 0x4b, 0xe2, 0xb5, 0x9c, 0x8d, 0x89, 0x24, 0x36, 0x26, 0x6c, 0xcd, 0x34, 0xb1, 0x35, 0x63, 0x73, 0x2a, 0x89, 0xcd, 0x29, 0xdb, 0x73, 0x4d, 0x6c, 0xcf, 0x39, 0xa0, 0x60, 0xa5, 0x65, 0x9e, 0x97, 0x90, 0x81, 0x43, 0x40, 0x1, 0x11, 0xd, 0xc, 0x58, 0x18, 0xde, 0x10, 0xd1, 0x60, 0x48, 0x45, 0x3a, 0x43, 0xa0, 0x8, 0x21, 0x95, 0x1c, 0xd3, 0x85, 0xa7, 0x77, 0xa6, 0x1d, 0x2a, 0x31, 0x1d, 0x7, 0x95, 0xfc, 0x6c, 0x36, 0x27, 0xa8, 0x74, 0x3b, 0xaa, 0xd, 0xa, 0x83, 0xb0, 0x5a, 0x8f, 0xeb, 0x2f, 0x33, 0xe2, 0x7a, 0xf7, 0xf, 0x16, 0xe6, 0x27, 0x9b, 0x59, 0x47, 0xab, 0xb6, 0xdf, 0x7, 0xda, 0xe9, 0x47, 0x3e, 0x8f, 0x56, 0x5b, 0x38, 0xdb, 0xd9, 0x1f, 0x2e, 0xcd, 0x4f, 0xb7, 0xf6, 0xc7, 0xeb, 0xe1, 0xf9, 0x3e, 0x5a, 0xeb, 0x7c, 0xff, 0x67, 0x80, 0xa1, 0x1d, 0x2, 0xc, 0x5b, 0x42, 0x38, 0xec, 0x21, 0x16, 0x7b, 0x8c, 0x67, 0x4, 0x64, 0xaa, 0x7e, 0x7, 0x99, 0x2a, 0x0, 0x99, 0x96, 0xa2, 0x5c, 0x7, 0x15, 0xe5, 0xd2, 0x61, 0xb6, 0x26, 0x40, 0x35, 0xf7, 0x11, 0x98, 0x6d, 0x9b, 0x38, 0x9f, 0x3, 0x40, 0xa3, 0x3d, 0xd2, 0x89, 0x50, 0x6b, 0x17, 0xc7, 0xdd, 0x24, 0xd4, 0x7a, 0x3b, 0x6e, 0x1d, 0xeb, 0xb5, 0x7, 0x9b, 0x15, 0xb4, 0xfb, 0xba, 0x17, 0xb8, 0xdd, 0x1, 0xbc, 0xbf, 0x57, 0xb1, 0xb4, 0xe0, 0xb0, 0x9b, 0x8a, 0x87, 0x3, 0x25, 0x97, 0x57, 0xcd, 0xa7, 0xfe, 0x56, 0xf3, 0xa9, 0xa1, 0xe6, 0xb3, 0x66, 0xd1, 0x29, 0x1a, 0x16, 0x9d, 0x22, 0xa1, 0xe8, 0x24, 0x54, 0xbd, 0x92, 0x34, 0x4d, 0x9e, 0x55, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0xaf, 0xc5, 0x7a, 0x0, 0xb3, 0x43, 0xaa, 0xfb, 0xee, 0x9f, 0xf1, 0x9c, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82, 0x00 };
+const unsigned char defaultDialogIcon10Name[] = { 0x77, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x2d, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x00 };
+const unsigned char defaultDialogIcon10Length[] = { 0x37, 0x32, 0x30, 0x00 };
+const unsigned char defaultDialogIcon10Data[] = { 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x40, 0x0, 0x0, 0x0, 0x40, 0x8, 0x3, 0x0, 0x0, 0x0, 0x9d, 0xb7, 0x81, 0xec, 0x0, 0x0, 0x0, 0x75, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x79, 0x59, 0x7d, 0x58, 0x0, 0x0, 0x0, 0x26, 0x74, 0x52, 0x4e, 0x53, 0x0, 0x7, 0xd2, 0xab, 0x12, 0x22, 0x73, 0x50, 0x7d, 0x25, 0xcb, 0xa7, 0xb8, 0x7c, 0x60, 0x2e, 0xfa, 0x8f, 0xeb, 0xe3, 0xd9, 0xc3, 0x9e, 0x84, 0x69, 0x1d, 0xf1, 0xcd, 0xb2, 0x91, 0xb9, 0xed, 0x49, 0x48, 0x36, 0x35, 0x93, 0xf2, 0x7e, 0x13, 0xd0, 0xd1, 0x0, 0x0, 0x1, 0xe4, 0x49, 0x44, 0x41, 0x54, 0x58, 0xc3, 0xed, 0x57, 0xd9, 0x96, 0xc2, 0x20, 0xc, 0x2d, 0x4c, 0x37, 0xb5, 0x8b, 0xb5, 0xda, 0xd5, 0xba, 0xf, 0xff, 0xff, 0x89, 0x73, 0xa, 0x8c, 0xa9, 0x8, 0xd, 0x1e, 0x4e, 0xdf, 0xcc, 0x63, 0x48, 0xd2, 0xe6, 0xde, 0x24, 0x4, 0xef, 0x2b, 0x8b, 0x8a, 0x7f, 0x8b, 0x9a, 0xba, 0xaa, 0xea, 0x26, 0xba, 0xf9, 0x9f, 0x7b, 0x7, 0xe1, 0x81, 0x4d, 0xe4, 0x10, 0x6, 0x9f, 0x78, 0x93, 0x90, 0xb2, 0x37, 0xa1, 0x21, 0xb1, 0xf5, 0xcf, 0x4a, 0xa6, 0x95, 0x32, 0xb3, 0x72, 0xbf, 0x50, 0x66, 0x14, 0x7a, 0xc1, 0xfd, 0x87, 0xa9, 0xc3, 0x8e, 0x26, 0x9, 0xdd, 0x4d, 0x35, 0x5, 0x86, 0xfc, 0xe9, 0x69, 0xba, 0x4e, 0x73, 0x22, 0x21, 0xc9, 0xd3, 0xf5, 0x53, 0x7d, 0x9a, 0x65, 0x64, 0xb5, 0x97, 0x66, 0x5d, 0xda, 0xbe, 0x9e, 0xb4, 0x71, 0x27, 0x8f, 0xf6, 0xab, 0x19, 0xff, 0xb3, 0xb0, 0xd9, 0xe, 0x9a, 0xcf, 0xf8, 0xc3, 0x56, 0x9c, 0x9e, 0x8d, 0x11, 0x7c, 0xf9, 0xfd, 0x75, 0x60, 0x88, 0x2f, 0x13, 0xd9, 0x9b, 0xb2, 0x90, 0xf9, 0x6f, 0x8c, 0x7c, 0x93, 0x8d, 0xb0, 0x48, 0xf4, 0xc7, 0x85, 0x38, 0x4d, 0xe7, 0x40, 0x4a, 0x67, 0xb8, 0xb8, 0x20, 0xfe, 0x42, 0x62, 0x61, 0x75, 0xd5, 0x1c, 0x51, 0xf1, 0xff, 0x6a, 0x4f, 0xa8, 0x78, 0x88, 0x2c, 0xa8, 0xa6, 0x7e, 0x5, 0x7e, 0x4a, 0xfe, 0x47, 0xc6, 0x8e, 0xa, 0xe, 0x2, 0xc9, 0xec, 0xd, 0x9f, 0x92, 0xf3, 0xa7, 0x7c, 0x2f, 0x1a, 0x95, 0x91, 0xc2, 0x5, 0x67, 0xb3, 0x54, 0x91, 0xe, 0x79, 0xdc, 0x41, 0xfd, 0x5f, 0x5d, 0x56, 0xf, 0x6e, 0x1a, 0xea, 0x10, 0xe8, 0x54, 0x82, 0x7f, 0x46, 0xed, 0x8f, 0x5a, 0x2e, 0x9d, 0x6, 0x85, 0x40, 0x32, 0x80, 0x6, 0x0, 0x26, 0x2, 0x4d, 0x6, 0xad, 0x5d, 0x80, 0x56, 0x93, 0xc3, 0x81, 0x53, 0xe0, 0xd9, 0x5, 0xf0, 0x7a, 0x3e, 0xe5, 0x5e, 0xd2, 0x82, 0xc, 0xb0, 0x0, 0x90, 0xc3, 0x14, 0xb0, 0x1b, 0xd7, 0xe4, 0xb6, 0x1, 0x72, 0x6e, 0x7e, 0x57, 0xf9, 0x66, 0xc4, 0x36, 0x0, 0x61, 0x6a, 0x7d, 0x34, 0x7c, 0x7e, 0x79, 0x48, 0x0, 0x10, 0x3e, 0xe5, 0x9a, 0x89, 0xa2, 0x6, 0x66, 0xb1, 0x0, 0x50, 0x35, 0xf5, 0x44, 0x51, 0x41, 0x97, 0x5b, 0x5, 0x48, 0x46, 0x7d, 0xe5, 0x1c, 0xc0, 0x39, 0x5, 0xc, 0x44, 0x68, 0x26, 0x1c, 0x44, 0xa0, 0x11, 0x6f, 0x67, 0xa0, 0x11, 0x29, 0x24, 0x18, 0x28, 0x48, 0x21, 0x29, 0xa5, 0x8c, 0x8c, 0x34, 0x28, 0xe5, 0xad, 0x8f, 0x34, 0x13, 0x8, 0xde, 0x4c, 0xd0, 0xce, 0x6, 0xc1, 0xdb, 0x39, 0x30, 0xe4, 0x90, 0xf5, 0x7d, 0x66, 0x68, 0xc6, 0x0, 0x19, 0x69, 0x80, 0x56, 0x8e, 0x8f, 0x34, 0x18, 0xaa, 0xba, 0xcb, 0xaa, 0xc0, 0x87, 0x2a, 0x8c, 0xf5, 0x95, 0xfd, 0x58, 0xb7, 0xba, 0x58, 0xc8, 0x58, 0x7, 0x4, 0xb9, 0x58, 0x5c, 0xaf, 0x36, 0xf7, 0xcb, 0x55, 0xbd, 0xde, 0x63, 0xb, 0xff, 0xc2, 0x75, 0xc1, 0x58, 0x64, 0xc5, 0xc1, 0x97, 0xac, 0x7, 0x2c, 0x59, 0x16, 0x6b, 0x5e, 0xfc, 0xb6, 0xe6, 0xfd, 0xc2, 0x9a, 0x67, 0xb7, 0x68, 0xf6, 0x31, 0x2c, 0x9a, 0x71, 0xff, 0x54, 0x27, 0xd8, 0xea, 0x5f, 0x60, 0xab, 0x2e, 0x2a, 0xd7, 0xb9, 0x65, 0xfb, 0xea, 0xbe, 0xee, 0xbb, 0x3f, 0x38, 0x96, 0x7f, 0xf2, 0x0, 0x23, 0xf7, 0xff, 0x47, 0xd7, 0xdd, 0xf7, 0xbe, 0xb2, 0xa4, 0xfc, 0x1, 0xb3, 0x34, 0x7e, 0xa8, 0x9d, 0x48, 0x16, 0xe7, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82, 0x00 };
+const unsigned char defaultDialogIcon11Name[] = { 0x77, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x2d, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x32, 0x78, 0x00 };
+const unsigned char defaultDialogIcon11Length[] = { 0x31, 0x32, 0x36, 0x32, 0x00 };
+const unsigned char defaultDialogIcon11Data[] = { 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x80, 0x0, 0x0, 0x0, 0x80, 0x8, 0x3, 0x0, 0x0, 0x0, 0xf4, 0xe0, 0x91, 0xf9, 0x0, 0x0, 0x0, 0x93, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7a, 0x79, 0x23, 0x75, 0x0, 0x0, 0x0, 0x30, 0x74, 0x52, 0x4e, 0x53, 0x0, 0xfb, 0x55, 0x42, 0xc, 0xd7, 0xb7, 0x8a, 0x82, 0x7, 0x19, 0xe5, 0xc0, 0x48, 0x2b, 0x68, 0x62, 0x4e, 0xee, 0x94, 0x39, 0x6f, 0x21, 0xe8, 0xe2, 0xb4, 0x90, 0x33, 0xd0, 0xbd, 0x9, 0xcb, 0x97, 0x3c, 0xf, 0xc5, 0xb1, 0xf6, 0xa8, 0x7c, 0x52, 0x26, 0x25, 0x14, 0xc6, 0x61, 0x5d, 0x11, 0x8d, 0xf, 0xdf, 0x6c, 0x0, 0x0, 0x3, 0xda, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0xec, 0x97, 0xd9, 0x72, 0xb3, 0x30, 0xc, 0x85, 0xe5, 0x42, 0xc0, 0x6c, 0x9, 0x94, 0xa5, 0x49, 0xc9, 0xbe, 0xa7, 0x49, 0x3a, 0x7e, 0xff, 0xa7, 0xfb, 0xff, 0x8b, 0xce, 0xd8, 0x10, 0x62, 0xd9, 0xc6, 0x74, 0x7a, 0x91, 0xef, 0x5a, 0x4c, 0xe, 0xd2, 0x39, 0x52, 0x80, 0x17, 0x2f, 0x5e, 0xbc, 0x78, 0x61, 0xce, 0x32, 0xbc, 0xd4, 0x4e, 0x96, 0x39, 0xf5, 0x25, 0x5c, 0xc2, 0xef, 0xe2, 0x3a, 0x65, 0xbe, 0x88, 0x98, 0x40, 0xb4, 0xc8, 0x4b, 0xc7, 0x85, 0xdf, 0x20, 0x70, 0xe8, 0x8d, 0xb0, 0x4e, 0xc8, 0x8d, 0x3a, 0x1, 0xc, 0x4b, 0x72, 0x3c, 0x30, 0x29, 0x87, 0x63, 0x2, 0x83, 0x31, 0xf6, 0x3f, 0x98, 0x2, 0x1f, 0xfe, 0x18, 0x86, 0x60, 0xe3, 0x31, 0x65, 0xbc, 0x2, 0x6c, 0xe3, 0xc4, 0x4c, 0x8b, 0xd8, 0xb1, 0xdb, 0xfc, 0x98, 0x69, 0x13, 0xdb, 0x1b, 0x84, 0xeb, 0x13, 0x66, 0x0, 0xf1, 0x2d, 0xe5, 0x32, 0x9b, 0x32, 0x43, 0xa6, 0x19, 0x58, 0xc0, 0x67, 0x3d, 0xf0, 0xfb, 0xb7, 0x7f, 0xf6, 0xb4, 0xc3, 0xd1, 0x6a, 0xbf, 0x3e, 0xa5, 0xe9, 0x69, 0xbd, 0x5f, 0x45, 0x4f, 0x67, 0x34, 0xeb, 0x39, 0x86, 0x6a, 0xc4, 0xba, 0x98, 0xd3, 0x22, 0x84, 0x6, 0x61, 0x41, 0xe7, 0xac, 0x8b, 0x51, 0xd5, 0x2b, 0x7c, 0xef, 0x1d, 0x6f, 0x1e, 0x97, 0xd5, 0x13, 0xb5, 0x65, 0xdc, 0xd1, 0x89, 0xf7, 0x1e, 0x81, 0x9c, 0x10, 0xd6, 0xc6, 0xbb, 0x5f, 0x41, 0xc2, 0xf5, 0xee, 0x3d, 0x2a, 0x9e, 0x80, 0x19, 0x41, 0xce, 0xda, 0xec, 0xa, 0x40, 0xd9, 0xec, 0x58, 0x9b, 0x3c, 0x30, 0xfa, 0xfd, 0xd9, 0xc3, 0x38, 0xcf, 0xa0, 0xc4, 0x79, 0xf4, 0x60, 0x45, 0x13, 0x5, 0x79, 0xfb, 0xc6, 0x4c, 0x2, 0x65, 0xed, 0x93, 0x8f, 0x76, 0xf, 0xc, 0xe6, 0xdf, 0x1a, 0x24, 0x75, 0xb5, 0xd2, 0x4b, 0x5b, 0xf6, 0xd1, 0xf6, 0x81, 0x43, 0x10, 0x2b, 0x6b, 0x6, 0x88, 0x6c, 0x34, 0xf3, 0xdf, 0x7c, 0x7c, 0xf4, 0x5, 0xda, 0x7c, 0x8d, 0x9a, 0xaf, 0x50, 0x69, 0x75, 0xb0, 0xf9, 0xb0, 0xb7, 0x5, 0x3, 0xb6, 0x5e, 0xf3, 0x25, 0x74, 0x66, 0xd8, 0xc, 0xc0, 0x27, 0x18, 0xf2, 0xd9, 0x8c, 0x82, 0xe1, 0xfd, 0x21, 0x29, 0x18, 0x93, 0x12, 0xa3, 0xcb, 0x94, 0x31, 0x91, 0x14, 0x7a, 0x90, 0x32, 0x91, 0x4c, 0xd1, 0x0, 0x53, 0xa4, 0xff, 0xc6, 0x53, 0x98, 0x2e, 0xf5, 0x7, 0xe0, 0x41, 0x4f, 0x3c, 0xed, 0x21, 0x8c, 0x89, 0x68, 0xdd, 0xad, 0xdc, 0xe8, 0xdf, 0x79, 0xfe, 0x8d, 0x94, 0x88, 0x81, 0x22, 0x63, 0xc0, 0x89, 0xc5, 0xf0, 0xca, 0xf3, 0x9f, 0x44, 0xec, 0x3f, 0x51, 0x22, 0xdf, 0x7, 0xe2, 0x4a, 0x89, 0x1, 0xc5, 0x11, 0x5, 0x3b, 0x20, 0xa3, 0x26, 0x3f, 0x65, 0xb5, 0xfa, 0x52, 0x75, 0xb4, 0x1a, 0x40, 0x41, 0xca, 0x9c, 0xfd, 0xb0, 0x2, 0x29, 0x94, 0x71, 0x16, 0xe8, 0x35, 0x17, 0xef, 0x9f, 0xb, 0x32, 0x42, 0x5e, 0x19, 0xca, 0x63, 0x25, 0xde, 0xc6, 0x2, 0x33, 0xad, 0xfa, 0x5, 0x4b, 0x78, 0x65, 0xa2, 0x7e, 0x59, 0x3d, 0x24, 0x2, 0x62, 0x2, 0x90, 0xfb, 0xff, 0xc6, 0x4b, 0xdf, 0x40, 0x4a, 0x20, 0x26, 0x61, 0xac, 0xbc, 0x3, 0xce, 0x60, 0x4b, 0x0, 0x9c, 0x95, 0x77, 0x81, 0x30, 0xad, 0x1d, 0xd8, 0x13, 0x0, 0x37, 0x5e, 0x1b, 0x29, 0x8e, 0x95, 0x15, 0x36, 0x5, 0x6c, 0x98, 0x9a, 0x61, 0x8e, 0x98, 0x59, 0x70, 0x1, 0xb8, 0xb9, 0x8f, 0x12, 0xb3, 0x1c, 0x78, 0xd9, 0xdd, 0x50, 0x0, 0x7e, 0x16, 0xf, 0x81, 0xca, 0x16, 0x24, 0x57, 0xbb, 0x2, 0xae, 0x44, 0x65, 0x1b, 0x52, 0x7c, 0x69, 0xe3, 0x2, 0xf0, 0xd, 0x4b, 0x55, 0xbc, 0x5a, 0xda, 0x16, 0x50, 0x2a, 0xe4, 0xcb, 0x15, 0xda, 0x54, 0xd9, 0x16, 0x50, 0x9, 0xe3, 0x75, 0x71, 0xb, 0xcc, 0xc1, 0xb6, 0x0, 0x98, 0xb, 0x26, 0xc0, 0xbb, 0x44, 0xed, 0xb, 0xa0, 0xf8, 0x7c, 0x73, 0x61, 0xb, 0xd9, 0x17, 0x50, 0xe0, 0x5f, 0x8a, 0xb, 0xe1, 0xbe, 0xda, 0x17, 0x10, 0xe2, 0x7f, 0xa, 0x22, 0x6e, 0x13, 0xb0, 0x2f, 0x0, 0xb8, 0xc5, 0xa7, 0xd0, 0xc9, 0x12, 0x39, 0x18, 0x7d, 0x5, 0x44, 0xbc, 0x7e, 0x89, 0xf5, 0x68, 0x35, 0x84, 0x80, 0x15, 0x36, 0xe1, 0xb, 0x2f, 0xd8, 0xf, 0x21, 0x60, 0xcf, 0xeb, 0x2f, 0xd0, 0x45, 0xcd, 0xb, 0xd6, 0x43, 0x8, 0x58, 0xf3, 0xfa, 0x1a, 0xdb, 0x43, 0xa7, 0x21, 0x4, 0x9c, 0xb0, 0x4d, 0x94, 0xf1, 0x82, 0xb4, 0x97, 0x0, 0xfc, 0x22, 0x67, 0x7f, 0x53, 0xc0, 0xbf, 0xf6, 0xcd, 0x6e, 0x5, 0x41, 0x20, 0xa, 0xc2, 0x7, 0xea, 0x26, 0xa2, 0x5f, 0x22, 0x4b, 0x2a, 0x92, 0xba, 0x2c, 0xf4, 0xfd, 0x9f, 0x2e, 0xc, 0xa, 0x44, 0xf2, 0x6b, 0x99, 0x85, 0xe3, 0x8a, 0x73, 0x6d, 0x37, 0x95, 0xbb, 0x67, 0xbe, 0x33, 0xe3, 0xfe, 0x13, 0xb8, 0xff, 0x9, 0xdd, 0x5f, 0x43, 0xf7, 0x83, 0x8, 0x8e, 0x62, 0xb0, 0x66, 0xc2, 0x51, 0xcc, 0x97, 0x11, 0x9b, 0x53, 0xe9, 0x32, 0xe2, 0xeb, 0x98, 0xed, 0xb9, 0x70, 0x1d, 0xf3, 0x40, 0xc2, 0x80, 0x62, 0x69, 0xc2, 0x40, 0xd2, 0x31, 0x92, 0xa1, 0x16, 0x87, 0xf7, 0x17, 0xba, 0x30, 0x13, 0x46, 0x32, 0x1a, 0x4a, 0x1, 0x52, 0xe5, 0x39, 0x40, 0x2a, 0x18, 0x4a, 0x61, 0x2c, 0x17, 0x44, 0x63, 0x39, 0x1b, 0x13, 0x49, 0x6c, 0x4c, 0xd8, 0x9a, 0x69, 0x62, 0x6b, 0xc6, 0xe6, 0x54, 0x12, 0x9b, 0x53, 0xb6, 0xe7, 0x9a, 0xd8, 0x9e, 0x33, 0xa0, 0x60, 0x6d, 0x8e, 0x59, 0x76, 0x4, 0x6, 0xe, 0x80, 0x42, 0x40, 0x34, 0x66, 0x57, 0xb8, 0xbc, 0x1, 0xd1, 0xa8, 0x90, 0xca, 0x56, 0x0, 0x14, 0x1, 0x52, 0xc9, 0x98, 0xce, 0xb6, 0x5f, 0xa6, 0x6d, 0xa, 0xa6, 0x63, 0x50, 0xc9, 0xcf, 0x2e, 0x43, 0x40, 0x65, 0xbf, 0x51, 0xad, 0xed, 0x1c, 0x60, 0xb5, 0x8e, 0xeb, 0x4f, 0x1, 0xb8, 0xbe, 0xff, 0xb, 0xb, 0xf7, 0x95, 0x4d, 0xd0, 0xd2, 0xaa, 0xac, 0xe7, 0x81, 0xb2, 0xfb, 0x91, 0xe6, 0xd2, 0x2a, 0x85, 0xb5, 0x9d, 0xff, 0xe2, 0xd2, 0x7d, 0x75, 0xeb, 0xbf, 0xbc, 0xf6, 0x5f, 0xdf, 0xc7, 0x9, 0x30, 0x94, 0xad, 0x0, 0x83, 0x6b, 0x84, 0x23, 0xdb, 0xa7, 0x15, 0x62, 0xf1, 0x8f, 0xf1, 0xf8, 0x7, 0x99, 0xe2, 0x46, 0xb9, 0xa2, 0x85, 0xd9, 0xa, 0x43, 0x15, 0x8f, 0xd6, 0xc7, 0xf2, 0x59, 0xc4, 0x38, 0xdf, 0xba, 0x3b, 0xce, 0xb7, 0x86, 0x38, 0x9f, 0x47, 0xa0, 0xb1, 0x48, 0x39, 0xd2, 0xc9, 0xa1, 0xd6, 0xe7, 0xb3, 0x3b, 0xd4, 0x7a, 0x9f, 0xa6, 0x1e, 0xeb, 0xed, 0x41, 0xb0, 0x59, 0x88, 0x76, 0x5f, 0x86, 0x12, 0x6e, 0xaf, 0x35, 0x39, 0x57, 0x41, 0x3a, 0x4f, 0x2c, 0xb6, 0x76, 0x7a, 0xc1, 0x41, 0xaf, 0x78, 0xcc, 0xab, 0x3f, 0x34, 0x6f, 0x57, 0x3c, 0x86, 0x52, 0x72, 0xf9, 0xd4, 0x7c, 0x6e, 0xbf, 0x6a, 0x3e, 0x37, 0xa8, 0xf9, 0xc4, 0x2d, 0x3a, 0x1d, 0x1a, 0x6f, 0x7c, 0x50, 0xd1, 0x29, 0xfd, 0xaa, 0xd7, 0xa8, 0x51, 0xa3, 0x46, 0xd, 0x4a, 0x2f, 0xb9, 0x87, 0x9d, 0xa4, 0x64, 0xb5, 0x51, 0x8a, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82, 0x00 };
+const unsigned char *defaultDialogIcons[] = { defaultDialogIcon0Name, defaultDialogIcon0Length, defaultDialogIcon0Data, defaultDialogIcon1Name, defaultDialogIcon1Length, defaultDialogIcon1Data, defaultDialogIcon2Name, defaultDialogIcon2Length, defaultDialogIcon2Data, defaultDialogIcon3Name, defaultDialogIcon3Length, defaultDialogIcon3Data, defaultDialogIcon4Name, defaultDialogIcon4Length, defaultDialogIcon4Data, defaultDialogIcon5Name, defaultDialogIcon5Length, defaultDialogIcon5Data, defaultDialogIcon6Name, defaultDialogIcon6Length, defaultDialogIcon6Data, defaultDialogIcon7Name, defaultDialogIcon7Length, defaultDialogIcon7Data, defaultDialogIcon8Name, defaultDialogIcon8Length, defaultDialogIcon8Data, defaultDialogIcon9Name, defaultDialogIcon9Length, defaultDialogIcon9Data, defaultDialogIcon10Name, defaultDialogIcon10Length, defaultDialogIcon10Data, defaultDialogIcon11Name, defaultDialogIcon11Length, defaultDialogIcon11Data, 0x00 };
diff --git a/v2/internal/ffenestri/effectstructs_windows.h b/v2/internal/ffenestri/effectstructs_windows.h
new file mode 100644
index 000000000..8313c4538
--- /dev/null
+++ b/v2/internal/ffenestri/effectstructs_windows.h
@@ -0,0 +1,64 @@
+// Credit: https://gist.github.com/ysc3839/b08d2bff1c7dacde529bed1d37e85ccf
+#pragma once
+
+typedef enum _WINDOWCOMPOSITIONATTRIB
+{
+ WCA_UNDEFINED = 0,
+ WCA_NCRENDERING_ENABLED = 1,
+ WCA_NCRENDERING_POLICY = 2,
+ WCA_TRANSITIONS_FORCEDISABLED = 3,
+ WCA_ALLOW_NCPAINT = 4,
+ WCA_CAPTION_BUTTON_BOUNDS = 5,
+ WCA_NONCLIENT_RTL_LAYOUT = 6,
+ WCA_FORCE_ICONIC_REPRESENTATION = 7,
+ WCA_EXTENDED_FRAME_BOUNDS = 8,
+ WCA_HAS_ICONIC_BITMAP = 9,
+ WCA_THEME_ATTRIBUTES = 10,
+ WCA_NCRENDERING_EXILED = 11,
+ WCA_NCADORNMENTINFO = 12,
+ WCA_EXCLUDED_FROM_LIVEPREVIEW = 13,
+ WCA_VIDEO_OVERLAY_ACTIVE = 14,
+ WCA_FORCE_ACTIVEWINDOW_APPEARANCE = 15,
+ WCA_DISALLOW_PEEK = 16,
+ WCA_CLOAK = 17,
+ WCA_CLOAKED = 18,
+ WCA_ACCENT_POLICY = 19,
+ WCA_FREEZE_REPRESENTATION = 20,
+ WCA_EVER_UNCLOAKED = 21,
+ WCA_VISUAL_OWNER = 22,
+ WCA_HOLOGRAPHIC = 23,
+ WCA_EXCLUDED_FROM_DDA = 24,
+ WCA_PASSIVEUPDATEMODE = 25,
+ WCA_USEDARKMODECOLORS = 26,
+ WCA_LAST = 27
+} WINDOWCOMPOSITIONATTRIB;
+
+typedef struct _WINDOWCOMPOSITIONATTRIBDATA
+{
+ WINDOWCOMPOSITIONATTRIB Attrib;
+ PVOID pvData;
+ SIZE_T cbData;
+} WINDOWCOMPOSITIONATTRIBDATA;
+
+typedef enum _ACCENT_STATE
+{
+ ACCENT_DISABLED = 0,
+ ACCENT_ENABLE_GRADIENT = 1,
+ ACCENT_ENABLE_TRANSPARENTGRADIENT = 2,
+ ACCENT_ENABLE_BLURBEHIND = 3,
+ ACCENT_ENABLE_ACRYLICBLURBEHIND = 4, // RS4 1803
+ ACCENT_ENABLE_HOSTBACKDROP = 5, // RS5 1809
+ ACCENT_INVALID_STATE = 6
+} ACCENT_STATE;
+
+typedef struct _ACCENT_POLICY
+{
+ ACCENT_STATE AccentState;
+ DWORD AccentFlags;
+ DWORD GradientColor;
+ DWORD AnimationId;
+} ACCENT_POLICY;
+
+typedef BOOL (WINAPI *pfnGetWindowCompositionAttribute)(HWND, WINDOWCOMPOSITIONATTRIBDATA*);
+
+typedef BOOL (WINAPI *pfnSetWindowCompositionAttribute)(HWND, WINDOWCOMPOSITIONATTRIBDATA*);
\ No newline at end of file
diff --git a/v2/internal/ffenestri/ffenestri.go b/v2/internal/ffenestri/ffenestri.go
new file mode 100644
index 000000000..15205b727
--- /dev/null
+++ b/v2/internal/ffenestri/ffenestri.go
@@ -0,0 +1,178 @@
+package ffenestri
+
+import (
+ "runtime"
+ "strings"
+ "unsafe"
+
+ "github.com/wailsapp/wails/v2/internal/menumanager"
+
+ "github.com/wailsapp/wails/v2/internal/logger"
+ "github.com/wailsapp/wails/v2/internal/messagedispatcher"
+ "github.com/wailsapp/wails/v2/pkg/options"
+)
+
+/*
+#cgo linux CFLAGS: -DFFENESTRI_LINUX=1
+#cgo linux pkg-config: gtk+-3.0 webkit2gtk-4.0
+
+#cgo darwin CFLAGS: -DFFENESTRI_DARWIN=1
+#cgo darwin LDFLAGS: -framework WebKit -lobjc
+
+#cgo windows CXXFLAGS: -std=c++11
+#cgo windows,amd64 LDFLAGS: -L./windows/x64 -lWebView2Loader -lgdi32 -lole32 -lShlwapi -luser32 -loleaut32 -ldwmapi
+
+#include
+#include "ffenestri.h"
+*/
+import "C"
+
+// Application is our main application object
+type Application struct {
+ config *options.App
+ memory []unsafe.Pointer
+
+ // This is the main app pointer
+ app *C.struct_Application
+
+ // Manages menus
+ menuManager *menumanager.Manager
+
+ // Logger
+ logger logger.CustomLogger
+}
+
+func (a *Application) saveMemoryReference(mem unsafe.Pointer) {
+ a.memory = append(a.memory, mem)
+}
+
+func (a *Application) string2CString(str string) *C.char {
+ result := C.CString(str)
+ a.saveMemoryReference(unsafe.Pointer(result))
+ return result
+}
+
+func init() {
+ runtime.LockOSThread()
+}
+
+// NewApplicationWithConfig creates a new application based on the given config
+func NewApplicationWithConfig(config *options.App, logger *logger.Logger, menuManager *menumanager.Manager) *Application {
+ return &Application{
+ config: config,
+ logger: logger.CustomLogger("Ffenestri"),
+ menuManager: menuManager,
+ }
+}
+
+func (a *Application) freeMemory() {
+ for _, mem := range a.memory {
+ // fmt.Printf("Freeing memory: %+v\n", mem)
+ C.free(mem)
+ }
+}
+
+// bool2Cint converts a Go boolean to a C integer
+func (a *Application) bool2Cint(value bool) C.int {
+ if value {
+ return C.int(1)
+ }
+ return C.int(0)
+}
+
+// dispatcher is the interface to send messages to
+var dispatcher *messagedispatcher.DispatchClient
+
+// Dispatcher is what we register out client with
+type Dispatcher interface {
+ RegisterClient(client messagedispatcher.Client) *messagedispatcher.DispatchClient
+}
+
+// DispatchClient is the means for passing messages to the backend
+type DispatchClient interface {
+ SendMessage(string)
+}
+
+func intToColour(colour int) (C.int, C.int, C.int, C.int) {
+ var alpha = C.int(colour & 0xFF)
+ var blue = C.int((colour >> 8) & 0xFF)
+ var green = C.int((colour >> 16) & 0xFF)
+ var red = C.int((colour >> 24) & 0xFF)
+ return red, green, blue, alpha
+}
+
+// Run the application
+func (a *Application) Run(incomingDispatcher Dispatcher, bindings string, debug bool) error {
+ title := a.string2CString(a.config.Title)
+ width := C.int(a.config.Width)
+ height := C.int(a.config.Height)
+ resizable := a.bool2Cint(!a.config.DisableResize)
+ devtools := a.bool2Cint(a.config.DevTools)
+ fullscreen := a.bool2Cint(a.config.Fullscreen)
+ startHidden := a.bool2Cint(a.config.StartHidden)
+ logLevel := C.int(a.config.LogLevel)
+ hideWindowOnClose := a.bool2Cint(a.config.HideWindowOnClose)
+ app := C.NewApplication(title, width, height, resizable, devtools, fullscreen, startHidden, logLevel, hideWindowOnClose)
+
+ // Save app reference
+ a.app = (*C.struct_Application)(app)
+
+ // Set Min Window Size
+ minWidth := C.int(a.config.MinWidth)
+ minHeight := C.int(a.config.MinHeight)
+ C.SetMinWindowSize(a.app, minWidth, minHeight)
+
+ // Set Max Window Size
+ maxWidth := C.int(a.config.MaxWidth)
+ maxHeight := C.int(a.config.MaxHeight)
+ C.SetMaxWindowSize(a.app, maxWidth, maxHeight)
+
+ // Set debug if needed
+ C.SetDebug(app, a.bool2Cint(debug))
+
+ if a.config.Frameless {
+ C.DisableFrame(a.app)
+ }
+
+ if a.config.RGBA != 0 {
+ r, g, b, alpha := intToColour(a.config.RGBA)
+ C.SetColour(a.app, r, g, b, alpha)
+ }
+
+ // Escape bindings so C doesn't freak out
+ bindings = strings.ReplaceAll(bindings, `"`, `\"`)
+
+ // Set bindings
+ C.SetBindings(app, a.string2CString(bindings))
+
+ // save the dispatcher in a package variable so that the C callbacks
+ // can access it
+ dispatcher = incomingDispatcher.RegisterClient(newClient(a))
+
+ // Process platform settings
+ err := a.processPlatformSettings()
+ if err != nil {
+ return err
+ }
+
+ // Check we could initialise the application
+ if app != nil {
+ // Yes - Save memory reference and run app, cleaning up afterwards
+ a.saveMemoryReference(unsafe.Pointer(app))
+ C.Run(app, 0, nil)
+ } else {
+ // Oh no! We couldn't initialise the application
+ a.logger.Fatal("Cannot initialise Application.")
+ }
+ //println("\n\n\n\n\n\nhererererer\n\n\n\n")
+ a.freeMemory()
+ return nil
+}
+
+// messageFromWindowCallback is called by any messages sent in
+// webkit to window.external.invoke. It relays the message on to
+// the dispatcher.
+//export messageFromWindowCallback
+func messageFromWindowCallback(data *C.char) {
+ dispatcher.DispatchMessage(C.GoString(data))
+}
diff --git a/v2/internal/ffenestri/ffenestri.h b/v2/internal/ffenestri/ffenestri.h
new file mode 100644
index 000000000..1bbc9d907
--- /dev/null
+++ b/v2/internal/ffenestri/ffenestri.h
@@ -0,0 +1,56 @@
+#ifndef __FFENESTRI_H__
+#define __FFENESTRI_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include
+struct Application;
+
+extern struct Application *NewApplication(const char *title, int width, int height, int resizable, int devtools, int fullscreen, int startHidden, int logLevel, int hideWindowOnClose);
+extern void SetMinWindowSize(struct Application*, int minWidth, int minHeight);
+extern void SetMaxWindowSize(struct Application*, int maxWidth, int maxHeight);
+extern void Run(struct Application*, int argc, char **argv);
+extern void DestroyApplication(struct Application*);
+extern void SetDebug(struct Application*, int flag);
+extern void SetBindings(struct Application*, const char *bindings);
+extern void ExecJS(struct Application*, const char *script);
+extern void Hide(struct Application*);
+extern void Show(struct Application*);
+extern void Center(struct Application*);
+extern void Maximise(struct Application*);
+extern void Unmaximise(struct Application*);
+extern void ToggleMaximise(struct Application*);
+extern void Minimise(struct Application*);
+extern void Unminimise(struct Application*);
+extern void ToggleMinimise(struct Application*);
+extern void SetColour(struct Application*, int red, int green, int blue, int alpha);
+extern void SetSize(struct Application*, int width, int height);
+extern void SetPosition(struct Application*, int x, int y);
+extern void Quit(struct Application*);
+extern void SetTitle(struct Application*, const char *title);
+extern void Fullscreen(struct Application*);
+extern void UnFullscreen(struct Application*);
+extern void ToggleFullscreen(struct Application*);
+extern void DisableFrame(struct Application*);
+extern void OpenDialog(struct Application*, char *callbackID, char *title, char *filters, char *defaultFilename, char *defaultDir, int allowFiles, int allowDirs, int allowMultiple, int showHiddenFiles, int canCreateDirectories, int resolvesAliases, int treatPackagesAsDirectories);
+extern void SaveDialog(struct Application*, char *callbackID, char *title, char *filters, char *defaultFilename, char *defaultDir, int showHiddenFiles, int canCreateDirectories, int treatPackagesAsDirectories);
+extern void MessageDialog(struct Application*, char *callbackID, char *type, char *title, char *message, char *icon, char *button1, char *button2, char *button3, char *button4, char *defaultButton, char *cancelButton);
+extern void DarkModeEnabled(struct Application*, char *callbackID);
+extern void SetApplicationMenu(struct Application*, const char *);
+extern void AddTrayMenu(struct Application*, const char *menuTrayJSON);
+extern void SetTrayMenu(struct Application*, const char *menuTrayJSON);
+extern void DeleteTrayMenuByID(struct Application*, const char *id);
+extern void UpdateTrayMenuLabel(struct Application*, const char* JSON);
+extern void AddContextMenu(struct Application*, char *contextMenuJSON);
+extern void UpdateContextMenu(struct Application*, char *contextMenuJSON);
+extern void WebviewIsTransparent(struct Application*);
+extern void WindowIsTranslucent(struct Application*);
+extern void* GetWindowHandle(struct Application*);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/v2/internal/ffenestri/ffenestri_client.go b/v2/internal/ffenestri/ffenestri_client.go
new file mode 100644
index 000000000..05af2cdf2
--- /dev/null
+++ b/v2/internal/ffenestri/ffenestri_client.go
@@ -0,0 +1,272 @@
+// +build !windows
+
+package ffenestri
+
+/*
+#include "ffenestri.h"
+*/
+import "C"
+
+import (
+ goruntime "runtime"
+ "strconv"
+ "strings"
+
+ "github.com/wailsapp/wails/v2/pkg/runtime"
+
+ "github.com/wailsapp/wails/v2/internal/logger"
+)
+
+// Client is our implementation of messageDispatcher.Client
+type Client struct {
+ app *Application
+ logger logger.CustomLogger
+}
+
+func newClient(app *Application) *Client {
+ return &Client{
+ app: app,
+ logger: app.logger,
+ }
+}
+
+// Quit the application
+func (c *Client) Quit() {
+ c.app.logger.Trace("Got shutdown message")
+ C.Quit(c.app.app)
+}
+
+// NotifyEvent will pass on the event message to the frontend
+func (c *Client) NotifyEvent(message string) {
+ eventMessage := `window.wails._.Notify(` + strconv.Quote(message) + `);`
+ c.app.logger.Trace("eventMessage = %+v", eventMessage)
+ C.ExecJS(c.app.app, c.app.string2CString(eventMessage))
+}
+
+// CallResult contains the result of the call from JS
+func (c *Client) CallResult(message string) {
+ callbackMessage := `window.wails._.Callback(` + strconv.Quote(message) + `);`
+ c.app.logger.Trace("callbackMessage = %+v", callbackMessage)
+ C.ExecJS(c.app.app, c.app.string2CString(callbackMessage))
+}
+
+// WindowSetTitle sets the window title to the given string
+func (c *Client) WindowSetTitle(title string) {
+ C.SetTitle(c.app.app, c.app.string2CString(title))
+}
+
+// WindowFullscreen will set the window to be fullscreen
+func (c *Client) WindowFullscreen() {
+ C.Fullscreen(c.app.app)
+}
+
+// WindowUnFullscreen will unfullscreen the window
+func (c *Client) WindowUnFullscreen() {
+ C.UnFullscreen(c.app.app)
+}
+
+// WindowShow will show the window
+func (c *Client) WindowShow() {
+ C.Show(c.app.app)
+}
+
+// WindowHide will hide the window
+func (c *Client) WindowHide() {
+ C.Hide(c.app.app)
+}
+
+// WindowCenter will hide the window
+func (c *Client) WindowCenter() {
+ C.Center(c.app.app)
+}
+
+// WindowMaximise will maximise the window
+func (c *Client) WindowMaximise() {
+ C.Maximise(c.app.app)
+}
+
+// WindowMinimise will minimise the window
+func (c *Client) WindowMinimise() {
+ C.Minimise(c.app.app)
+}
+
+// WindowUnmaximise will unmaximise the window
+func (c *Client) WindowUnmaximise() {
+ C.Unmaximise(c.app.app)
+}
+
+// WindowUnminimise will unminimise the window
+func (c *Client) WindowUnminimise() {
+ C.Unminimise(c.app.app)
+}
+
+// WindowPosition will position the window to x,y on the
+// monitor that the window is mostly on
+func (c *Client) WindowPosition(x int, y int) {
+ C.SetPosition(c.app.app, C.int(x), C.int(y))
+}
+
+// WindowSize will resize the window to the given
+// width and height
+func (c *Client) WindowSize(width int, height int) {
+ C.SetSize(c.app.app, C.int(width), C.int(height))
+}
+
+func (c *Client) WindowSetMinSize(width int, height int) {
+ C.SetMinWindowSize(c.app.app, C.int(width), C.int(height))
+}
+
+func (c *Client) WindowSetMaxSize(width int, height int) {
+ C.SetMaxWindowSize(c.app.app, C.int(width), C.int(height))
+}
+
+// WindowSetColour sets the window colour
+func (c *Client) WindowSetColour(colour int) {
+ r, g, b, a := intToColour(colour)
+ C.SetColour(c.app.app, r, g, b, a)
+}
+
+// OpenFileDialog will open a dialog with the given title and filter
+func (c *Client) OpenFileDialog(dialogOptions runtime.OpenDialogOptions, callbackID string) {
+ filters := []string{}
+ if goruntime.GOOS == "darwin" {
+ for _, filter := range dialogOptions.Filters {
+ filters = append(filters, strings.Split(filter.Pattern, ",")...)
+ }
+ }
+ C.OpenDialog(c.app.app,
+ c.app.string2CString(callbackID),
+ c.app.string2CString(dialogOptions.Title),
+ c.app.string2CString(strings.Join(filters, ";")),
+ c.app.string2CString(dialogOptions.DefaultFilename),
+ c.app.string2CString(dialogOptions.DefaultDirectory),
+ c.app.bool2Cint(dialogOptions.AllowFiles),
+ c.app.bool2Cint(dialogOptions.AllowDirectories),
+ c.app.bool2Cint(false),
+ c.app.bool2Cint(dialogOptions.ShowHiddenFiles),
+ c.app.bool2Cint(dialogOptions.CanCreateDirectories),
+ c.app.bool2Cint(dialogOptions.ResolvesAliases),
+ c.app.bool2Cint(dialogOptions.TreatPackagesAsDirectories),
+ )
+}
+
+// OpenDirectoryDialog will open a dialog with the given title and filter
+func (c *Client) OpenDirectoryDialog(dialogOptions runtime.OpenDialogOptions, callbackID string) {
+ filters := []string{}
+ if goruntime.GOOS == "darwin" {
+ for _, filter := range dialogOptions.Filters {
+ filters = append(filters, strings.Split(filter.Pattern, ",")...)
+ }
+ }
+ C.OpenDialog(c.app.app,
+ c.app.string2CString(callbackID),
+ c.app.string2CString(dialogOptions.Title),
+ c.app.string2CString(strings.Join(filters, ";")),
+ c.app.string2CString(dialogOptions.DefaultFilename),
+ c.app.string2CString(dialogOptions.DefaultDirectory),
+ c.app.bool2Cint(false), // Files
+ c.app.bool2Cint(true), // Directories
+ c.app.bool2Cint(false), // Multiple
+ c.app.bool2Cint(dialogOptions.ShowHiddenFiles),
+ c.app.bool2Cint(dialogOptions.CanCreateDirectories),
+ c.app.bool2Cint(dialogOptions.ResolvesAliases),
+ c.app.bool2Cint(dialogOptions.TreatPackagesAsDirectories),
+ )
+}
+
+// OpenMultipleFilesDialog will open a dialog with the given title and filter
+func (c *Client) OpenMultipleFilesDialog(dialogOptions runtime.OpenDialogOptions, callbackID string) {
+ filters := []string{}
+ if goruntime.GOOS == "darwin" {
+ for _, filter := range dialogOptions.Filters {
+ filters = append(filters, strings.Split(filter.Pattern, ",")...)
+ }
+ }
+ C.OpenDialog(c.app.app,
+ c.app.string2CString(callbackID),
+ c.app.string2CString(dialogOptions.Title),
+ c.app.string2CString(strings.Join(filters, ";")),
+ c.app.string2CString(dialogOptions.DefaultFilename),
+ c.app.string2CString(dialogOptions.DefaultDirectory),
+ c.app.bool2Cint(dialogOptions.AllowFiles),
+ c.app.bool2Cint(dialogOptions.AllowDirectories),
+ c.app.bool2Cint(true),
+ c.app.bool2Cint(dialogOptions.ShowHiddenFiles),
+ c.app.bool2Cint(dialogOptions.CanCreateDirectories),
+ c.app.bool2Cint(dialogOptions.ResolvesAliases),
+ c.app.bool2Cint(dialogOptions.TreatPackagesAsDirectories),
+ )
+}
+
+// SaveDialog will open a dialog with the given title and filter
+func (c *Client) SaveDialog(dialogOptions *runtime.SaveDialogOptions, callbackID string) {
+ filters := []string{}
+ if goruntime.GOOS == "darwin" {
+ for _, filter := range dialogOptions.Filters {
+ filters = append(filters, strings.Split(filter.Pattern, ",")...)
+ }
+ }
+ C.SaveDialog(c.app.app,
+ c.app.string2CString(callbackID),
+ c.app.string2CString(dialogOptions.Title),
+ c.app.string2CString(strings.Join(filters, ";")),
+ c.app.string2CString(dialogOptions.DefaultFilename),
+ c.app.string2CString(dialogOptions.DefaultDirectory),
+ c.app.bool2Cint(dialogOptions.ShowHiddenFiles),
+ c.app.bool2Cint(dialogOptions.CanCreateDirectories),
+ c.app.bool2Cint(dialogOptions.TreatPackagesAsDirectories),
+ )
+}
+
+// MessageDialog will open a message dialog with the given options
+func (c *Client) MessageDialog(dialogOptions runtime.MessageDialogOptions, callbackID string) {
+
+ // Sanity check button length
+ if len(dialogOptions.Buttons) > 4 {
+ c.app.logger.Error("Given %d message dialog buttons. Maximum is 4", len(dialogOptions.Buttons))
+ return
+ }
+
+ // Process buttons
+ buttons := []string{"", "", "", ""}
+ for i, button := range dialogOptions.Buttons {
+ buttons[i] = button
+ }
+
+ C.MessageDialog(c.app.app,
+ c.app.string2CString(callbackID),
+ c.app.string2CString(string(dialogOptions.Type)),
+ c.app.string2CString(dialogOptions.Title),
+ c.app.string2CString(dialogOptions.Message),
+ c.app.string2CString(dialogOptions.Icon),
+ c.app.string2CString(buttons[0]),
+ c.app.string2CString(buttons[1]),
+ c.app.string2CString(buttons[2]),
+ c.app.string2CString(buttons[3]),
+ c.app.string2CString(dialogOptions.DefaultButton),
+ c.app.string2CString(dialogOptions.CancelButton))
+}
+
+func (c *Client) DarkModeEnabled(callbackID string) {
+ C.DarkModeEnabled(c.app.app, c.app.string2CString(callbackID))
+}
+
+func (c *Client) SetApplicationMenu(applicationMenuJSON string) {
+ C.SetApplicationMenu(c.app.app, c.app.string2CString(applicationMenuJSON))
+}
+
+func (c *Client) SetTrayMenu(trayMenuJSON string) {
+ C.SetTrayMenu(c.app.app, c.app.string2CString(trayMenuJSON))
+}
+
+func (c *Client) UpdateTrayMenuLabel(JSON string) {
+ C.UpdateTrayMenuLabel(c.app.app, c.app.string2CString(JSON))
+}
+
+func (c *Client) UpdateContextMenu(contextMenuJSON string) {
+ C.UpdateContextMenu(c.app.app, c.app.string2CString(contextMenuJSON))
+}
+
+func (c *Client) DeleteTrayMenuByID(id string) {
+ C.DeleteTrayMenuByID(c.app.app, c.app.string2CString(id))
+}
diff --git a/v2/internal/ffenestri/ffenestri_client_windows.go b/v2/internal/ffenestri/ffenestri_client_windows.go
new file mode 100644
index 000000000..542fbf79a
--- /dev/null
+++ b/v2/internal/ffenestri/ffenestri_client_windows.go
@@ -0,0 +1,308 @@
+// +build windows
+
+package ffenestri
+
+/*
+#include "ffenestri.h"
+*/
+import "C"
+
+import (
+ "encoding/json"
+ "github.com/leaanthony/go-common-file-dialog/cfd"
+ "github.com/wailsapp/wails/v2/pkg/runtime"
+ "golang.org/x/sys/windows"
+ "log"
+ "strconv"
+ "syscall"
+
+ "github.com/wailsapp/wails/v2/internal/logger"
+)
+
+// Client is our implementation of messageDispatcher.Client
+type Client struct {
+ app *Application
+ logger logger.CustomLogger
+}
+
+func newClient(app *Application) *Client {
+ return &Client{
+ app: app,
+ logger: app.logger,
+ }
+}
+
+// Quit the application
+func (c *Client) Quit() {
+ c.app.logger.Trace("Got shutdown message")
+ C.Quit(c.app.app)
+}
+
+// NotifyEvent will pass on the event message to the frontend
+func (c *Client) NotifyEvent(message string) {
+ eventMessage := `window.wails._.Notify(` + strconv.Quote(message) + `);`
+ c.app.logger.Trace("eventMessage = %+v", eventMessage)
+ C.ExecJS(c.app.app, c.app.string2CString(eventMessage))
+}
+
+// CallResult contains the result of the call from JS
+func (c *Client) CallResult(message string) {
+ callbackMessage := `window.wails._.Callback(` + strconv.Quote(message) + `);`
+ c.app.logger.Trace("callbackMessage = %+v", callbackMessage)
+ C.ExecJS(c.app.app, c.app.string2CString(callbackMessage))
+}
+
+// WindowSetTitle sets the window title to the given string
+func (c *Client) WindowSetTitle(title string) {
+ C.SetTitle(c.app.app, c.app.string2CString(title))
+}
+
+// WindowFullscreen will set the window to be fullscreen
+func (c *Client) WindowFullscreen() {
+ C.Fullscreen(c.app.app)
+}
+
+// WindowUnFullscreen will unfullscreen the window
+func (c *Client) WindowUnFullscreen() {
+ C.UnFullscreen(c.app.app)
+}
+
+// WindowShow will show the window
+func (c *Client) WindowShow() {
+ C.Show(c.app.app)
+}
+
+// WindowHide will hide the window
+func (c *Client) WindowHide() {
+ C.Hide(c.app.app)
+}
+
+// WindowCenter will hide the window
+func (c *Client) WindowCenter() {
+ C.Center(c.app.app)
+}
+
+// WindowMaximise will maximise the window
+func (c *Client) WindowMaximise() {
+ C.Maximise(c.app.app)
+}
+
+// WindowMinimise will minimise the window
+func (c *Client) WindowMinimise() {
+ C.Minimise(c.app.app)
+}
+
+// WindowUnmaximise will unmaximise the window
+func (c *Client) WindowUnmaximise() {
+ C.Unmaximise(c.app.app)
+}
+
+// WindowUnminimise will unminimise the window
+func (c *Client) WindowUnminimise() {
+ C.Unminimise(c.app.app)
+}
+
+// WindowPosition will position the window to x,y on the
+// monitor that the window is mostly on
+func (c *Client) WindowPosition(x int, y int) {
+ C.SetPosition(c.app.app, C.int(x), C.int(y))
+}
+
+// WindowSize will resize the window to the given
+// width and height
+func (c *Client) WindowSize(width int, height int) {
+ C.SetSize(c.app.app, C.int(width), C.int(height))
+}
+
+// WindowSetMinSize sets the minimum window size
+func (c *Client) WindowSetMinSize(width int, height int) {
+ C.SetMinWindowSize(c.app.app, C.int(width), C.int(height))
+}
+
+// WindowSetMaxSize sets the maximum window size
+func (c *Client) WindowSetMaxSize(width int, height int) {
+ C.SetMaxWindowSize(c.app.app, C.int(width), C.int(height))
+}
+
+// WindowSetColour sets the window colour
+func (c *Client) WindowSetColour(colour int) {
+ r, g, b, a := intToColour(colour)
+ C.SetColour(c.app.app, r, g, b, a)
+}
+
+func convertFilters(filters []runtime.FileFilter) []cfd.FileFilter {
+ var result []cfd.FileFilter
+ for _, filter := range filters {
+ result = append(result, cfd.FileFilter(filter))
+ }
+ return result
+}
+
+// OpenFileDialog will open a dialog with the given title and filter
+func (c *Client) OpenFileDialog(options runtime.OpenDialogOptions, callbackID string) {
+ config := cfd.DialogConfig{
+ Folder: options.DefaultDirectory,
+ FileFilters: convertFilters(options.Filters),
+ FileName: options.DefaultFilename,
+ }
+ thisdialog, err := cfd.NewOpenFileDialog(config)
+ if err != nil {
+ log.Fatal(err)
+ }
+ thisdialog.SetParentWindowHandle(uintptr(C.GetWindowHandle(c.app.app)))
+ defer func(thisdialog cfd.OpenFileDialog) {
+ err := thisdialog.Release()
+ if err != nil {
+ log.Fatal(err)
+ }
+ }(thisdialog)
+ result, err := thisdialog.ShowAndGetResult()
+ if err != nil && err != cfd.ErrorCancelled {
+ log.Fatal(err)
+ }
+
+ dispatcher.DispatchMessage("DO" + callbackID + "|" + result)
+}
+
+// OpenDirectoryDialog will open a dialog with the given title and filter
+func (c *Client) OpenDirectoryDialog(dialogOptions runtime.OpenDialogOptions, callbackID string) {
+ config := cfd.DialogConfig{
+ Title: dialogOptions.Title,
+ Role: "PickFolder",
+ Folder: dialogOptions.DefaultDirectory,
+ }
+ thisDialog, err := cfd.NewSelectFolderDialog(config)
+ if err != nil {
+ log.Fatal()
+ }
+ thisDialog.SetParentWindowHandle(uintptr(C.GetWindowHandle(c.app.app)))
+ defer func(thisDialog cfd.SelectFolderDialog) {
+ err := thisDialog.Release()
+ if err != nil {
+ log.Fatal(err)
+ }
+ }(thisDialog)
+ result, err := thisDialog.ShowAndGetResult()
+ if err != nil && err != cfd.ErrorCancelled {
+ log.Fatal(err)
+ }
+ dispatcher.DispatchMessage("DD" + callbackID + "|" + result)
+}
+
+// OpenMultipleFilesDialog will open a dialog with the given title and filter
+func (c *Client) OpenMultipleFilesDialog(dialogOptions runtime.OpenDialogOptions, callbackID string) {
+ config := cfd.DialogConfig{
+ Title: dialogOptions.Title,
+ Role: "OpenMultipleFiles",
+ FileFilters: convertFilters(dialogOptions.Filters),
+ FileName: dialogOptions.DefaultFilename,
+ Folder: dialogOptions.DefaultDirectory,
+ }
+ thisdialog, err := cfd.NewOpenMultipleFilesDialog(config)
+ if err != nil {
+ log.Fatal(err)
+ }
+ thisdialog.SetParentWindowHandle(uintptr(C.GetWindowHandle(c.app.app)))
+ defer func(thisdialog cfd.OpenMultipleFilesDialog) {
+ err := thisdialog.Release()
+ if err != nil {
+ log.Fatal(err)
+ }
+ }(thisdialog)
+ result, err := thisdialog.ShowAndGetResults()
+ if err != nil && err != cfd.ErrorCancelled {
+ log.Fatal(err)
+ }
+ resultJSON, err := json.Marshal(result)
+ if err != nil {
+ log.Fatal(err)
+ }
+ dispatcher.DispatchMessage("D*" + callbackID + "|" + string(resultJSON))
+}
+
+// SaveDialog will open a dialog with the given title and filter
+func (c *Client) SaveDialog(dialogOptions runtime.SaveDialogOptions, callbackID string) {
+ saveDialog, err := cfd.NewSaveFileDialog(cfd.DialogConfig{
+ Title: dialogOptions.Title,
+ Role: "SaveFile",
+ FileFilters: convertFilters(dialogOptions.Filters),
+ FileName: dialogOptions.DefaultFilename,
+ Folder: dialogOptions.DefaultDirectory,
+ })
+ if err != nil {
+ log.Fatal(err)
+ }
+ saveDialog.SetParentWindowHandle(uintptr(C.GetWindowHandle(c.app.app)))
+ err = saveDialog.Show()
+ if err != nil {
+ log.Fatal(err)
+ }
+ result, err := saveDialog.GetResult()
+ if err != nil && err != cfd.ErrorCancelled {
+ log.Fatal(err)
+ }
+ dispatcher.DispatchMessage("DS" + callbackID + "|" + result)
+}
+
+// MessageDialog will open a message dialog with the given options
+func (c *Client) MessageDialog(options runtime.MessageDialogOptions, callbackID string) {
+
+ title, err := syscall.UTF16PtrFromString(options.Title)
+ if err != nil {
+ log.Fatal(err)
+ }
+ message, err := syscall.UTF16PtrFromString(options.Message)
+ if err != nil {
+ log.Fatal(err)
+ }
+ var flags uint32
+ switch options.Type {
+ case runtime.InfoDialog:
+ flags = windows.MB_OK | windows.MB_ICONINFORMATION
+ case runtime.ErrorDialog:
+ flags = windows.MB_ICONERROR | windows.MB_OK
+ case runtime.QuestionDialog:
+ flags = windows.MB_YESNO
+ case runtime.WarningDialog:
+ flags = windows.MB_OK | windows.MB_ICONWARNING
+ }
+
+ button, _ := windows.MessageBox(windows.HWND(C.GetWindowHandle(c.app.app)), message, title, flags|windows.MB_SYSTEMMODAL)
+ // This maps MessageBox return values to strings
+ responses := []string{"", "Ok", "Cancel", "Abort", "Retry", "Ignore", "Yes", "No", "", "", "Try Again", "Continue"}
+ result := "Error"
+ if int(button) < len(responses) {
+ result = responses[button]
+ }
+ dispatcher.DispatchMessage("DM" + callbackID + "|" + result)
+}
+
+// DarkModeEnabled sets the application to use dark mode
+func (c *Client) DarkModeEnabled(callbackID string) {
+ C.DarkModeEnabled(c.app.app, c.app.string2CString(callbackID))
+}
+
+// SetApplicationMenu sets the application menu
+func (c *Client) SetApplicationMenu(_ string) {
+ c.updateApplicationMenu()
+}
+
+// SetTrayMenu sets the tray menu
+func (c *Client) SetTrayMenu(trayMenuJSON string) {
+ C.SetTrayMenu(c.app.app, c.app.string2CString(trayMenuJSON))
+}
+
+// UpdateTrayMenuLabel updates a tray menu label
+func (c *Client) UpdateTrayMenuLabel(JSON string) {
+ C.UpdateTrayMenuLabel(c.app.app, c.app.string2CString(JSON))
+}
+
+// UpdateContextMenu will update the current context menu
+func (c *Client) UpdateContextMenu(contextMenuJSON string) {
+ C.UpdateContextMenu(c.app.app, c.app.string2CString(contextMenuJSON))
+}
+
+// DeleteTrayMenuByID will remove a tray menu based on the given id
+func (c *Client) DeleteTrayMenuByID(id string) {
+ C.DeleteTrayMenuByID(c.app.app, c.app.string2CString(id))
+}
diff --git a/v2/internal/ffenestri/ffenestri_darwin.c b/v2/internal/ffenestri/ffenestri_darwin.c
new file mode 100644
index 000000000..1bdb49176
--- /dev/null
+++ b/v2/internal/ffenestri/ffenestri_darwin.c
@@ -0,0 +1,1817 @@
+
+#ifdef FFENESTRI_DARWIN
+
+#include "ffenestri_darwin.h"
+#include "menu_darwin.h"
+#include "contextmenus_darwin.h"
+#include "traymenustore_darwin.h"
+#include "traymenu_darwin.h"
+
+// References to assets
+#include "assets.h"
+extern const unsigned char runtime;
+
+// Dialog icons
+extern const unsigned char *defaultDialogIcons[];
+#include "userdialogicons.h"
+
+// MAIN DEBUG FLAG
+int debug;
+
+// A cache for all our dialog icons
+struct hashmap_s dialogIconCache;
+
+// Dispatch Method
+typedef void (^dispatchMethod)(void);
+
+// Message Dialog
+void MessageDialog(struct Application *app, char *callbackID, char *type, char *title, char *message, char *icon, char *button1, char *button2, char *button3, char *button4, char *defaultButton, char *cancelButton);
+
+TrayMenuStore *TrayMenuStoreSingleton;
+
+// dispatch will execute the given `func` pointer
+void dispatch(dispatchMethod func) {
+ dispatch_async(dispatch_get_main_queue(), func);
+}
+// yes command simply returns YES!
+BOOL yes(id self, SEL cmd)
+{
+ return YES;
+}
+
+// no command simply returns NO!
+BOOL no(id self, SEL cmd)
+{
+ return NO;
+}
+
+// Prints a hashmap entry
+int hashmap_log(void *const context, struct hashmap_element_s *const e) {
+ printf("%s: %p ", (char*)e->key, e->data);
+ return 0;
+}
+
+void filelog(const char *message) {
+ FILE *fp = fopen("/tmp/wailslog.txt", "ab");
+ if (fp != NULL)
+ {
+ fputs(message, fp);
+ fclose(fp);
+ }
+}
+
+// The delegate class for tray menus
+Class trayMenuDelegateClass;
+
+// Utility function to visualise a hashmap
+void dumpHashmap(const char *name, struct hashmap_s *hashmap) {
+ printf("%s = { ", name);
+ if (0!=hashmap_iterate_pairs(hashmap, hashmap_log, NULL)) {
+ fprintf(stderr, "Failed to dump hashmap entries\n");
+ }
+ printf("}\n");
+}
+
+extern void messageFromWindowCallback(const char *);
+typedef void (*ffenestriCallback)(const char *);
+
+void HideMouse() {
+ msg_reg(c("NSCursor"), s("hide"));
+}
+
+void ShowMouse() {
+ msg_reg(c("NSCursor"), s("unhide"));
+}
+
+OSVersion getOSVersion() {
+ id processInfo = msg_reg(c("NSProcessInfo"), s("processInfo"));
+ return GET_OSVERSION(processInfo);
+}
+
+struct Application {
+
+ // Cocoa data
+ id application;
+ id delegate;
+ id windowDelegate;
+ id mainWindow;
+ id wkwebview;
+ id manager;
+ id config;
+ id mouseEvent;
+ id mouseDownMonitor;
+ id mouseUpMonitor;
+ int activationPolicy;
+ id pool;
+
+ // Window Data
+ const char *title;
+ int width;
+ int height;
+ int minWidth;
+ int minHeight;
+ int maxWidth;
+ int maxHeight;
+ int resizable;
+ int devtools;
+ int fullscreen;
+ CGFloat red;
+ CGFloat green;
+ CGFloat blue;
+ CGFloat alpha;
+ int webviewIsTranparent;
+ const char *appearance;
+ int decorations;
+ int logLevel;
+ int hideWindowOnClose;
+
+ // Features
+ int frame;
+ int startHidden;
+ int maximised;
+ int titlebarAppearsTransparent;
+ int hideTitle;
+ int hideTitleBar;
+ int fullSizeContent;
+ int useToolBar;
+ int hideToolbarSeparator;
+ int WindowIsTranslucent;
+ int hasURLHandlers;
+ const char *startupURL;
+
+ // Menu
+ Menu *applicationMenu;
+
+ // Context Menus
+ ContextMenuStore *contextMenuStore;
+
+ // Callback
+ ffenestriCallback sendMessageToBackend;
+
+ // Bindings
+ const char *bindings;
+
+ // shutting down flag
+ bool shuttingDown;
+
+ // Running flag
+ bool running;
+
+};
+
+// Debug works like sprintf but mutes if the global debug flag is true
+// Credit: https://stackoverflow.com/a/20639708
+
+#define MAXMESSAGE 1024*10
+char logbuffer[MAXMESSAGE];
+
+void Debug(struct Application *app, const char *message, ... ) {
+ if ( debug ) {
+ const char *temp = concat("LTFfenestri (C) | ", message);
+ va_list args;
+ va_start(args, message);
+ vsnprintf(logbuffer, MAXMESSAGE, temp, args);
+ app->sendMessageToBackend(&logbuffer[0]);
+ MEMFREE(temp);
+ va_end(args);
+ }
+}
+
+void Error(struct Application *app, const char *message, ... ) {
+ const char *temp = concat("LEFfenestri (C) | ", message);
+ va_list args;
+ va_start(args, message);
+ vsnprintf(logbuffer, MAXMESSAGE, temp, args);
+ app->sendMessageToBackend(&logbuffer[0]);
+ MEMFREE(temp);
+ va_end(args);
+}
+
+void Fatal(struct Application *app, const char *message, ... ) {
+ const char *temp = concat("LFFfenestri (C) | ", message);
+ va_list args;
+ va_start(args, message);
+ vsnprintf(logbuffer, MAXMESSAGE, temp, args);
+ app->sendMessageToBackend(&logbuffer[0]);
+ MEMFREE(temp);
+ va_end(args);
+}
+
+// Requires NSString input EG lookupStringConstant(str("NSFontAttributeName"))
+void* lookupStringConstant(id constantName) {
+ void ** dataPtr = CFBundleGetDataPointerForName(CFBundleGetBundleWithIdentifier((CFStringRef)str("com.apple.AppKit")), (CFStringRef) constantName);
+ return (dataPtr ? *dataPtr : nil);
+}
+
+bool isRetina(struct Application *app) {
+ CGFloat scale = GET_BACKINGSCALEFACTOR(app->mainWindow);
+ if( (int)scale == 1 ) {
+ return false;
+ }
+ return true;
+}
+
+void TitlebarAppearsTransparent(struct Application* app) {
+ app->titlebarAppearsTransparent = 1;
+}
+
+void HideTitle(struct Application *app) {
+ app->hideTitle = 1;
+}
+
+void HideTitleBar(struct Application *app) {
+ app->hideTitleBar = 1;
+}
+
+void HideToolbarSeparator(struct Application *app) {
+ app->hideToolbarSeparator = 1;
+}
+
+void UseToolbar(struct Application *app) {
+ app->useToolBar = 1;
+}
+
+// WebviewIsTransparent will make the webview transparent
+// revealing the Cocoa window underneath
+void WebviewIsTransparent(struct Application *app) {
+ app->webviewIsTranparent = 1;
+}
+
+// SetAppearance will set the window's Appearance to the
+// given value
+void SetAppearance(struct Application *app, const char *appearance) {
+ app->appearance = appearance;
+}
+
+
+void applyWindowColour(struct Application *app) {
+ // Apply the colour only if the window has been created
+ if( app->mainWindow != NULL ) {
+ ON_MAIN_THREAD(
+ id colour = ((id(*)(id, SEL, CGFloat, CGFloat, CGFloat, CGFloat))objc_msgSend)(c("NSColor"), s("colorWithCalibratedRed:green:blue:alpha:"),
+ (CGFloat)app->red / (CGFloat)255.0,
+ (CGFloat)app->green / (CGFloat)255.0,
+ (CGFloat)app->blue / (CGFloat)255.0,
+ (CGFloat)app->alpha / (CGFloat)255.0);
+ msg_id(app->mainWindow, s("setBackgroundColor:"), colour);
+ );
+ }
+}
+
+void SetColour(struct Application *app, int red, int green, int blue, int alpha) {
+ // Guard against calling during shutdown
+ if( app->shuttingDown ) return;
+
+ app->red = (CGFloat)red;
+ app->green = (CGFloat)green;
+ app->blue = (CGFloat)blue;
+ app->alpha = (CGFloat)alpha;
+
+ applyWindowColour(app);
+}
+
+void FullSizeContent(struct Application *app) {
+ app->fullSizeContent = 1;
+}
+
+void Hide(struct Application *app) {
+ // Guard against calling during shutdown
+ if( app->shuttingDown ) return;
+
+ ON_MAIN_THREAD(
+ msg_reg(app->mainWindow, s("orderOut:"));
+ );
+}
+
+void Show(struct Application *app) {
+ // Guard against calling during shutdown
+ if( app->shuttingDown ) return;
+
+ ON_MAIN_THREAD(
+ msg_id(app->mainWindow, s("makeKeyAndOrderFront:"), NULL);
+ msg_bool(app->application, s("activateIgnoringOtherApps:"), YES);
+ );
+}
+
+void WindowIsTranslucent(struct Application *app) {
+ app->WindowIsTranslucent = 1;
+}
+
+// Sends messages to the backend
+void messageHandler(id self, SEL cmd, id contentController, id message) {
+ struct Application *app = (struct Application *)objc_getAssociatedObject(
+ self, "application");
+ const char *name = (const char *)msg_reg(msg_reg(message, s("name")), s("UTF8String"));
+ if( strcmp(name, "error") == 0 ) {
+ printf("There was a Javascript error. Please open the devtools for more information.\n");
+ // Show app if we are in debug mode
+ if( debug ) {
+ Show(app);
+ MessageDialog(app, "", "error", "Javascript Error", "There was a Javascript error. Please open the devtools for more information.", "", "", "", "","","","");
+ }
+ } else if( strcmp(name, "completed") == 0) {
+ // Delete handler
+ msg_id(app->manager, s("removeScriptMessageHandlerForName:"), str("completed"));
+
+ // TODO: Notify backend we're ready and get them to call back for the Show()
+ if (app->startHidden == 0) {
+ Show(app);
+ }
+
+ // TODO: Check this actually does reduce flicker
+ ((id(*)(id, SEL, id, id))objc_msgSend)(app->config, s("setValue:forKey:"), msg_bool(c("NSNumber"), s("numberWithBool:"), 0), str("suppressesIncrementalRendering"));
+
+ // We are now running!
+ app->running = true;
+
+
+ // Notify backend we are ready (system startup)
+ const char *readyMessage = "SS";
+ if( app->startupURL == NULL ) {
+ app->sendMessageToBackend("SS");
+ return;
+ }
+ readyMessage = concat("SS", app->startupURL);
+ app->sendMessageToBackend(readyMessage);
+ MEMFREE(readyMessage);
+
+ } else if( strcmp(name, "windowDrag") == 0 ) {
+ // Guard against null events
+ if( app->mouseEvent != NULL ) {
+ HideMouse();
+ ON_MAIN_THREAD(
+ msg_id(app->mainWindow, s("performWindowDragWithEvent:"), app->mouseEvent);
+ );
+ }
+ } else if( strcmp(name, "contextMenu") == 0 ) {
+
+ // Did we get a context menu selector?
+ if( message == NULL) {
+ return;
+ }
+
+ const char *contextMenuMessage = cstr(msg_reg(message, s("body")));
+
+ if( contextMenuMessage == NULL ) {
+ Debug(app, "EMPTY CONTEXT MENU MESSAGE!!\n");
+ return;
+ }
+
+ // Parse the message
+ JsonNode *contextMenuMessageJSON = json_decode(contextMenuMessage);
+ if( contextMenuMessageJSON == NULL ) {
+ Debug(app, "Error decoding context menu message: %s", contextMenuMessage);
+ return;
+ }
+
+ // Get menu ID
+ JsonNode *contextMenuIDNode = json_find_member(contextMenuMessageJSON, "id");
+ if( contextMenuIDNode == NULL ) {
+ Debug(app, "Error decoding context menu ID: %s", contextMenuMessage);
+ json_delete(contextMenuMessageJSON);
+ return;
+ }
+ if( contextMenuIDNode->tag != JSON_STRING ) {
+ Debug(app, "Error decoding context menu ID (Not a string): %s", contextMenuMessage);
+ json_delete(contextMenuMessageJSON);
+ return;
+ }
+
+ // Get menu Data
+ JsonNode *contextMenuDataNode = json_find_member(contextMenuMessageJSON, "data");
+ if( contextMenuDataNode == NULL ) {
+ Debug(app, "Error decoding context menu data: %s", contextMenuMessage);
+ json_delete(contextMenuMessageJSON);
+ return;
+ }
+ if( contextMenuDataNode->tag != JSON_STRING ) {
+ Debug(app, "Error decoding context menu data (Not a string): %s", contextMenuMessage);
+ json_delete(contextMenuMessageJSON);
+ return;
+ }
+
+ // We need to copy these as the JSON node will be destroyed on this thread and the
+ // string data will become corrupt. These need to be freed by the context menu code.
+ const char* contextMenuID = STRCOPY(contextMenuIDNode->string_);
+ const char* contextMenuData = STRCOPY(contextMenuDataNode->string_);
+
+ ON_MAIN_THREAD(
+ ShowContextMenu(app->contextMenuStore, app->mainWindow, contextMenuID, contextMenuData);
+ );
+
+ json_delete(contextMenuMessageJSON);
+
+ } else {
+ // const char *m = (const char *)msg(msg(message, s("body")), s("UTF8String"));
+ const char *m = cstr(msg_reg(message, s("body")));
+ app->sendMessageToBackend(m);
+ }
+}
+
+// closeWindow is called when the close button is pressed
+void closeWindow(id self, SEL cmd, id sender) {
+ struct Application *app = (struct Application *) objc_getAssociatedObject(self, "application");
+ app->sendMessageToBackend("WC");
+}
+
+bool isDarkMode(struct Application *app) {
+ id userDefaults = msg_reg(c("NSUserDefaults"), s("standardUserDefaults"));
+ const char *mode = cstr(msg_id(userDefaults, s("stringForKey:"), str("AppleInterfaceStyle")));
+ return ( mode != NULL && strcmp(mode, "Dark") == 0 );
+}
+
+void ExecJS(struct Application *app, const char *js) {
+ ON_MAIN_THREAD(
+ ((id(*)(id, SEL, id, id))objc_msgSend)(app->wkwebview,
+ s("evaluateJavaScript:completionHandler:"),
+ str(js),
+ NULL);
+ );
+}
+
+void willFinishLaunching(id self, SEL cmd, id sender) {
+ struct Application *app = (struct Application *) objc_getAssociatedObject(self, "application");
+ // If there are URL Handlers, register a listener for them
+ if( app->hasURLHandlers ) {
+ id eventManager = msg_reg(c("NSAppleEventManager"), s("sharedAppleEventManager"));
+ ((id(*)(id, SEL, id, SEL, int, int))objc_msgSend)(eventManager, s("setEventHandler:andSelector:forEventClass:andEventID:"), self, s("getUrl:withReplyEvent:"), kInternetEventClass, kAEGetURL);
+ }
+ messageFromWindowCallback("Ej{\"name\":\"wails:launched\",\"data\":[]}");
+}
+
+void emitThemeChange(struct Application *app) {
+ bool currentThemeIsDark = isDarkMode(app);
+ if (currentThemeIsDark) {
+ messageFromWindowCallback("Ej{\"name\":\"wails:system:themechange\",\"data\":[true]}");
+ } else {
+ messageFromWindowCallback("Ej{\"name\":\"wails:system:themechange\",\"data\":[false]}");
+ }
+}
+
+void themeChanged(id self, SEL cmd, id sender) {
+ struct Application *app = (struct Application *)objc_getAssociatedObject(
+ self, "application");
+// emitThemeChange(app);
+ bool currentThemeIsDark = isDarkMode(app);
+ if ( currentThemeIsDark ) {
+ ExecJS(app, "window.wails.Events.Emit( 'wails:system:themechange', true );");
+ } else {
+ ExecJS(app, "window.wails.Events.Emit( 'wails:system:themechange', false );");
+ }
+}
+
+int releaseNSObject(void *const context, struct hashmap_element_s *const e) {
+ msg_reg(e->data, s("release"));
+ return -1;
+}
+
+void destroyContextMenus(struct Application *app) {
+ DeleteContextMenuStore(app->contextMenuStore);
+}
+
+void freeDialogIconCache(struct Application *app) {
+ // Release the dialog cache images
+ if( hashmap_num_entries(&dialogIconCache) > 0 ) {
+ if (0!=hashmap_iterate_pairs(&dialogIconCache, releaseNSObject, NULL)) {
+ Fatal(app, "failed to release hashmap entries!");
+ }
+ }
+
+ //Free radio groups hashmap
+ hashmap_destroy(&dialogIconCache);
+}
+
+void DestroyApplication(struct Application *app) {
+ app->shuttingDown = true;
+ Debug(app, "Destroying Application");
+
+ // Free the bindings
+ if (app->bindings != NULL) {
+ MEMFREE(app->bindings);
+ } else {
+ Debug(app, "Almost a double free for app->bindings");
+ }
+
+ if( app->startupURL != NULL ) {
+ MEMFREE(app->startupURL);
+ }
+
+ // Remove mouse monitors
+ if( app->mouseDownMonitor != NULL ) {
+ msg_id( c("NSEvent"), s("removeMonitor:"), app->mouseDownMonitor);
+ }
+ if( app->mouseUpMonitor != NULL ) {
+ msg_id( c("NSEvent"), s("removeMonitor:"), app->mouseUpMonitor);
+ }
+
+ // Delete the application menu if we have one
+ if( app->applicationMenu != NULL ) {
+ DeleteMenu(app->applicationMenu);
+ }
+
+ // Delete the tray menu store
+ DeleteTrayMenuStore(TrayMenuStoreSingleton);
+
+ // Delete the context menu store
+ DeleteContextMenuStore(app->contextMenuStore);
+
+ // Destroy the context menus
+ destroyContextMenus(app);
+
+ // Free dialog icon cache
+ freeDialogIconCache(app);
+
+ // Unload the tray Icons
+ UnloadTrayIcons();
+
+ // Remove script handlers
+ msg_id(app->manager, s("removeScriptMessageHandlerForName:"), str("contextMenu"));
+ msg_id(app->manager, s("removeScriptMessageHandlerForName:"), str("windowDrag"));
+ msg_id(app->manager, s("removeScriptMessageHandlerForName:"), str("external"));
+ msg_id(app->manager, s("removeScriptMessageHandlerForName:"), str("error"));
+
+ // Close main window
+ if( app->windowDelegate != NULL ) {
+ msg_reg(app->windowDelegate, s("release"));
+ msg_id(app->mainWindow, s("setDelegate:"), NULL);
+ }
+
+// msg(app->mainWindow, s("close"));
+
+
+ Debug(app, "Finished Destroying Application");
+}
+
+// SetTitle sets the main window title to the given string
+void SetTitle(struct Application *app, const char *title) {
+ // Guard against calling during shutdown
+ if( app->shuttingDown ) return;
+
+ Debug(app, "SetTitle Called");
+ ON_MAIN_THREAD(
+ msg_id(app->mainWindow, s("setTitle:"), str(title));
+ );
+}
+
+void ToggleFullscreen(struct Application *app) {
+ ON_MAIN_THREAD(
+ app->fullscreen = !app->fullscreen;
+ MAIN_WINDOW_CALL("toggleFullScreen:");
+ );
+}
+
+bool isFullScreen(struct Application *app) {
+ long mask = (long)msg_reg(app->mainWindow, s("styleMask"));
+ bool result = (mask & NSWindowStyleMaskFullscreen) == NSWindowStyleMaskFullscreen;
+ return result;
+}
+
+// Fullscreen sets the main window to be fullscreen
+void Fullscreen(struct Application *app) {
+ // Guard against calling during shutdown
+ if( app->shuttingDown ) return;
+
+ Debug(app, "Fullscreen Called");
+ if( ! isFullScreen(app) ) {
+ ToggleFullscreen(app);
+ }
+}
+
+// UnFullscreen resets the main window after a fullscreen
+void UnFullscreen(struct Application *app) {
+ // Guard against calling during shutdown
+ if( app->shuttingDown ) return;
+
+ Debug(app, "UnFullscreen Called");
+ if( isFullScreen(app) ) {
+ ToggleFullscreen(app);
+ }
+}
+
+void Center(struct Application *app) {
+ // Guard against calling during shutdown
+ if( app->shuttingDown ) return;
+
+ Debug(app, "Center Called");
+ ON_MAIN_THREAD(
+ MAIN_WINDOW_CALL("center");
+ );
+}
+
+void ToggleMaximise(struct Application *app) {
+ ON_MAIN_THREAD(
+ app->maximised = !app->maximised;
+ MAIN_WINDOW_CALL("zoom:");
+ );
+}
+
+void Maximise(struct Application *app) {
+ // Guard against calling during shutdown
+ if( app->shuttingDown ) return;
+
+ if( app->maximised == 0) {
+ ToggleMaximise(app);
+ }
+}
+
+void Unmaximise(struct Application *app) {
+ // Guard against calling during shutdown
+ if( app->shuttingDown ) return;
+
+ if( app->maximised == 1) {
+ ToggleMaximise(app);
+ }
+}
+
+void Minimise(struct Application *app) {
+ // Guard against calling during shutdown
+ if( app->shuttingDown ) return;
+
+ ON_MAIN_THREAD(
+ MAIN_WINDOW_CALL("miniaturize:");
+ );
+ }
+void Unminimise(struct Application *app) {
+ // Guard against calling during shutdown
+ if( app->shuttingDown ) return;
+
+ ON_MAIN_THREAD(
+ MAIN_WINDOW_CALL("deminiaturize:");
+ );
+}
+
+id getCurrentScreen(struct Application *app) {
+ id screen = NULL;
+ screen = msg_reg(app->mainWindow, s("screen"));
+ if( screen == NULL ) {
+ screen = msg_reg(c("NSScreen"), u("mainScreen"));
+ }
+ return screen;
+}
+
+void dumpFrame(struct Application *app, const char *message, CGRect frame) {
+ Debug(app, message);
+ Debug(app, "origin.x %f", frame.origin.x);
+ Debug(app, "origin.y %f", frame.origin.y);
+ Debug(app, "size.width %f", frame.size.width);
+ Debug(app, "size.height %f", frame.size.height);
+}
+
+void SetSize(struct Application *app, int width, int height) {
+ // Guard against calling during shutdown
+ if( app->shuttingDown ) return;
+
+ ON_MAIN_THREAD(
+ id screen = getCurrentScreen(app);
+
+ // Get the rect for the window
+ CGRect frame = GET_FRAME(app->mainWindow);
+
+ // Credit: https://github.com/patr0nus/DeskGap/blob/73c0ac9f2c73f55b6e81f64f6673a7962b5719cd/lib/src/platform/mac/util/NSScreen%2BGeometry.m
+ frame.origin.y = (frame.origin.y + frame.size.height) - (float)height;
+ frame.size.width = (float)width;
+ frame.size.height = (float)height;
+
+ ((id(*)(id, SEL, CGRect, BOOL, BOOL))objc_msgSend)(app->mainWindow, s("setFrame:display:animate:"), frame, 1, 0);
+ );
+}
+
+void SetPosition(struct Application *app, int x, int y) {
+ // Guard against calling during shutdown
+ if( app->shuttingDown ) return;
+
+ ON_MAIN_THREAD(
+ id screen = getCurrentScreen(app);
+ CGRect screenFrame = GET_FRAME(screen);
+ CGRect windowFrame = GET_FRAME(app->mainWindow);
+
+ windowFrame.origin.x = screenFrame.origin.x + (float)x;
+ windowFrame.origin.y = (screenFrame.origin.y + screenFrame.size.height) - windowFrame.size.height - (float)y;
+ ((id(*)(id, SEL, CGRect, BOOL, BOOL))objc_msgSend)(app->mainWindow, s("setFrame:display:animate:"), windowFrame, 1, 0);
+ );
+}
+
+void processDialogButton(id alert, char *buttonTitle, char *cancelButton, char *defaultButton) {
+ // If this button is set
+ if( STR_HAS_CHARS(buttonTitle) ) {
+ id button = msg_id(alert, s("addButtonWithTitle:"), str(buttonTitle));
+ if ( STREQ( buttonTitle, defaultButton) ) {
+ msg_id(button, s("setKeyEquivalent:"), str("\r"));
+ }
+ if ( STREQ( buttonTitle, cancelButton) ) {
+ msg_id(button, s("setKeyEquivalent:"), str("\033"));
+ }
+ }
+}
+
+void MessageDialog(struct Application *app, char *callbackID, char *type, char *title, char *message, char *icon, char *button1, char *button2, char *button3, char *button4, char *defaultButton, char *cancelButton) {
+ // Guard against calling during shutdown
+ if( app->shuttingDown ) return;
+
+ ON_MAIN_THREAD(
+ id alert = ALLOC_INIT("NSAlert");
+ char *dialogType = type;
+ char *dialogIcon = type;
+
+ // Default to info type
+ if( dialogType == NULL ) {
+ dialogType = "info";
+ }
+
+ // Set the dialog style
+ if( STREQ(dialogType, "info") || STREQ(dialogType, "question") ) {
+ msg_uint(alert, s("setAlertStyle:"), NSAlertStyleInformational);
+ } else if( STREQ(dialogType, "warning") ) {
+ msg_uint(alert, s("setAlertStyle:"), NSAlertStyleWarning);
+ } else if( STREQ(dialogType, "error") ) {
+ msg_uint(alert, s("setAlertStyle:"), NSAlertStyleCritical);
+ }
+
+ // Set title if given
+ if( strlen(title) > 0 ) {
+ msg_id(alert, s("setMessageText:"), str(title));
+ }
+
+ // Set message if given
+ if( strlen(message) > 0) {
+ msg_id(alert, s("setInformativeText:"), str(message));
+ }
+
+ // Process buttons
+ processDialogButton(alert, button1, cancelButton, defaultButton);
+ processDialogButton(alert, button2, cancelButton, defaultButton);
+ processDialogButton(alert, button3, cancelButton, defaultButton);
+ processDialogButton(alert, button4, cancelButton, defaultButton);
+
+ // Check for custom dialog icon
+ if( strlen(icon) > 0 ) {
+ dialogIcon = icon;
+ }
+
+ // TODO: move dialog icons + methods to own file
+
+ // Determine what dialog icon we are looking for
+ id dialogImage = NULL;
+ // Look for `name-theme2x` first
+ char *themeIcon = concat(dialogIcon, (isDarkMode(app) ? "-dark" : "-light") );
+ if( isRetina(app) ) {
+ char *dialogIcon2x = concat(themeIcon, "2x");
+ dialogImage = hashmap_get(&dialogIconCache, dialogIcon2x, strlen(dialogIcon2x));
+// if (dialogImage != NULL ) printf("Using %s\n", dialogIcon2x);
+ MEMFREE(dialogIcon2x);
+
+ // Now look for non-themed icon `name2x`
+ if ( dialogImage == NULL ) {
+ dialogIcon2x = concat(dialogIcon, "2x");
+ dialogImage = hashmap_get(&dialogIconCache, dialogIcon2x, strlen(dialogIcon2x));
+// if (dialogImage != NULL ) printf("Using %s\n", dialogIcon2x);
+ MEMFREE(dialogIcon2x);
+ }
+ }
+
+ // If we don't have a retina icon, try the 1x name-theme icon
+ if( dialogImage == NULL ) {
+ dialogImage = hashmap_get(&dialogIconCache, themeIcon, strlen(themeIcon));
+// if (dialogImage != NULL ) printf("Using %s\n", themeIcon);
+ }
+
+ // Free the theme icon memory
+ MEMFREE(themeIcon);
+
+ // Finally try the name itself
+ if( dialogImage == NULL ) {
+ dialogImage = hashmap_get(&dialogIconCache, dialogIcon, strlen(dialogIcon));
+// if (dialogImage != NULL ) printf("Using %s\n", dialogIcon);
+ }
+
+ if (dialogImage != NULL ) {
+ msg_id(alert, s("setIcon:"), dialogImage);
+ }
+
+ // Run modal
+ char *buttonPressed;
+ long response = (long)msg_reg(alert, s("runModal"));
+ if( response == NSAlertFirstButtonReturn ) {
+ buttonPressed = button1;
+ }
+ else if( response == NSAlertSecondButtonReturn ) {
+ buttonPressed = button2;
+ }
+ else if( response == NSAlertThirdButtonReturn ) {
+ buttonPressed = button3;
+ }
+ else {
+ buttonPressed = button4;
+ }
+
+ if ( STR_HAS_CHARS(callbackID) ) {
+ // Construct callback message. Format "DM|"
+ const char *callback = concat("DM", callbackID);
+ const char *header = concat(callback, "|");
+ const char *responseMessage = concat(header, buttonPressed);
+
+ // Send message to backend
+ app->sendMessageToBackend(responseMessage);
+
+ // Free memory
+ MEMFREE(header);
+ MEMFREE(callback);
+ MEMFREE(responseMessage);
+ }
+ );
+}
+
+// OpenDialog opens a dialog to select files/directories
+void OpenDialog(struct Application *app, char *callbackID, char *title, char *filters, char *defaultFilename, char *defaultDir, int allowFiles, int allowDirs, int allowMultiple, int showHiddenFiles, int canCreateDirectories, int resolvesAliases, int treatPackagesAsDirectories) {
+ // Guard against calling during shutdown
+ if( app->shuttingDown ) return;
+
+ Debug(app, "OpenDialog Called with callback id: %s", callbackID);
+
+ // Create an open panel
+ ON_MAIN_THREAD(
+
+ // Create the dialog
+ id dialog = msg_reg(c("NSOpenPanel"), s("openPanel"));
+
+ // Valid but appears to do nothing.... :/
+ msg_id(dialog, s("setTitle:"), str(title));
+
+ // Filters
+ if( filters != NULL && strlen(filters) > 0) {
+ id filterString = msg_id_id(str(filters), s("stringByReplacingOccurrencesOfString:withString:"), str("*."), str(""));
+ filterString = msg_id_id(filterString, s("stringByReplacingOccurrencesOfString:withString:"), str(" "), str(""));
+ id filterList = msg_id(filterString, s("componentsSeparatedByString:"), str(","));
+ msg_id(dialog, s("setAllowedFileTypes:"), filterList);
+ } else {
+ msg_bool(dialog, s("setAllowsOtherFileTypes:"), YES);
+ }
+
+ // Default Directory
+ if( defaultDir != NULL && strlen(defaultDir) > 0 ) {
+ msg_id(dialog, s("setDirectoryURL:"), url(defaultDir));
+ }
+
+ // Default Filename
+ if( defaultFilename != NULL && strlen(defaultFilename) > 0 ) {
+ msg_id(dialog, s("setNameFieldStringValue:"), str(defaultFilename));
+ }
+
+ // Setup Options
+ msg_bool(dialog, s("setCanChooseFiles:"), allowFiles);
+ msg_bool(dialog, s("setCanChooseDirectories:"), allowDirs);
+ msg_bool(dialog, s("setAllowsMultipleSelection:"), allowMultiple);
+ msg_bool(dialog, s("setShowsHiddenFiles:"), showHiddenFiles);
+ msg_bool(dialog, s("setCanCreateDirectories:"), canCreateDirectories);
+ msg_bool(dialog, s("setResolvesAliases:"), resolvesAliases);
+ msg_bool(dialog, s("setTreatsFilePackagesAsDirectories:"), treatPackagesAsDirectories);
+
+ // Setup callback handler
+ ((id(*)(id, SEL, id, void (^)(id)))objc_msgSend)(dialog, s("beginSheetModalForWindow:completionHandler:"), app->mainWindow, ^(id result) {
+
+ // Create the response JSON object
+ JsonNode *response = json_mkarray();
+
+ // If the user selected some files
+ if( result == (id)1 ) {
+ // Grab the URLs returned
+ id urls = msg_reg(dialog, s("URLs"));
+
+ // Iterate over all the selected files
+ long noOfResults = (long)msg_reg(urls, s("count"));
+ for( int index = 0; index < noOfResults; index++ ) {
+
+ // Extract the filename
+ id url = msg_int(urls, s("objectAtIndex:"), index);
+ const char *filename = (const char *)msg_reg(msg_reg(url, s("path")), s("UTF8String"));
+
+ // Add the the response array
+ json_append_element(response, json_mkstring(filename));
+ }
+ }
+
+ // Create JSON string and free json memory
+ char *encoded = json_stringify(response, "");
+ json_delete(response);
+
+ // Construct callback message. Format "D|"
+ const char *callback = concat("DO", callbackID);
+ const char *header = concat(callback, "|");
+ const char *responseMessage = concat(header, encoded);
+
+ // Send message to backend
+ app->sendMessageToBackend(responseMessage);
+
+ // Free memory
+ MEMFREE(header);
+ MEMFREE(callback);
+ MEMFREE(responseMessage);
+ });
+
+ msg_id( c("NSApp"), s("runModalForWindow:"), app->mainWindow);
+ );
+}
+
+// SaveDialog opens a dialog to select files/directories
+void SaveDialog(struct Application *app, char *callbackID, char *title, char *filters, char *defaultFilename, char *defaultDir, int showHiddenFiles, int canCreateDirectories, int treatPackagesAsDirectories) {
+ // Guard against calling during shutdown
+ if( app->shuttingDown ) return;
+
+ Debug(app, "SaveDialog Called with callback id: %s", callbackID);
+
+ // Create an open panel
+ ON_MAIN_THREAD(
+
+ // Create the dialog
+ id dialog = msg_reg(c("NSSavePanel"), s("savePanel"));
+
+ // Valid but appears to do nothing.... :/
+ msg_id(dialog, s("setTitle:"), str(title));
+
+ // Filters
+ if( filters != NULL && strlen(filters) > 0) {
+ id filterString = msg_id_id(str(filters), s("stringByReplacingOccurrencesOfString:withString:"), str("*."), str(""));
+ filterString = msg_id_id(filterString, s("stringByReplacingOccurrencesOfString:withString:"), str(" "), str(""));
+ id filterList = msg_id(filterString, s("componentsSeparatedByString:"), str(","));
+ msg_id(dialog, s("setAllowedFileTypes:"), filterList);
+ } else {
+ msg_bool(dialog, s("setAllowsOtherFileTypes:"), YES);
+ }
+
+ // Default Directory
+ if( defaultDir != NULL && strlen(defaultDir) > 0 ) {
+ msg_id(dialog, s("setDirectoryURL:"), url(defaultDir));
+ }
+
+ // Default Filename
+ if( defaultFilename != NULL && strlen(defaultFilename) > 0 ) {
+ msg_id(dialog, s("setNameFieldStringValue:"), str(defaultFilename));
+ }
+
+ // Setup Options
+ msg_bool(dialog, s("setShowsHiddenFiles:"), showHiddenFiles);
+ msg_bool(dialog, s("setCanCreateDirectories:"), canCreateDirectories);
+ msg_bool(dialog, s("setTreatsFilePackagesAsDirectories:"), treatPackagesAsDirectories);
+
+ // Setup callback handler
+ ((id(*)(id, SEL, id, void (^)(id)))objc_msgSend)(dialog, s("beginSheetModalForWindow:completionHandler:"), app->mainWindow, ^(id result) {
+
+ // Default is blank
+ const char *filename = "";
+
+ // If the user selected some files
+ if( result == (id)1 ) {
+ // Grab the URL returned
+ id url = msg_reg(dialog, s("URL"));
+ filename = (const char *)msg_reg(msg_reg(url, s("path")), s("UTF8String"));
+ }
+
+ // Construct callback message. Format "DS|"
+ const char *callback = concat("DS", callbackID);
+ const char *header = concat(callback, "|");
+ const char *responseMessage = concat(header, filename);
+
+ // Send message to backend
+ app->sendMessageToBackend(responseMessage);
+
+ // Free memory
+ MEMFREE(header);
+ MEMFREE(callback);
+ MEMFREE(responseMessage);
+ });
+
+ msg_id( c("NSApp"), s("runModalForWindow:"), app->mainWindow);
+ );
+}
+
+const char *invoke = "window.wailsInvoke=function(message){window.webkit.messageHandlers.external.postMessage(message);};window.wailsDrag=function(message){window.webkit.messageHandlers.windowDrag.postMessage(message);};window.wailsContextMenuMessage=function(message){window.webkit.messageHandlers.contextMenu.postMessage(message);};";
+
+// DisableFrame disables the window frame
+void DisableFrame(struct Application *app)
+{
+ app->frame = 0;
+}
+
+void setMinMaxSize(struct Application *app)
+{
+ // Guard against calling during shutdown
+ if( app->shuttingDown ) return;
+
+ if (app->maxHeight > 0 && app->maxWidth > 0)
+ {
+ ((id(*)(id, SEL, CGSize))objc_msgSend)(app->mainWindow, s("setMaxSize:"), CGSizeMake(app->maxWidth, app->maxHeight));
+ }
+ if (app->minHeight > 0 && app->minWidth > 0)
+ {
+ ((id(*)(id, SEL, CGSize))objc_msgSend)(app->mainWindow, s("setMinSize:"), CGSizeMake(app->minWidth, app->minHeight));
+ }
+
+ // Calculate if window needs resizing
+ int newWidth = app->width;
+ int newHeight = app->height;
+
+ if (app->maxWidth > 0 && app->width > app->maxWidth) newWidth = app->maxWidth;
+ if (app->minWidth > 0 && app->width < app->minWidth) newWidth = app->minWidth;
+ if (app->maxHeight > 0 && app->height > app->maxHeight ) newHeight = app->maxHeight;
+ if (app->minHeight > 0 && app->height < app->minHeight ) newHeight = app->minHeight;
+
+ // If we have any change, resize window
+ if ( newWidth != app->width || newHeight != app->height ) {
+ SetSize(app, newWidth, newHeight);
+ }
+}
+
+void SetMinWindowSize(struct Application *app, int minWidth, int minHeight)
+{
+ // Guard against calling during shutdown
+ if( app->shuttingDown ) return;
+
+ app->minWidth = minWidth;
+ app->minHeight = minHeight;
+
+ // Apply if the window is created
+ if( app->mainWindow != NULL ) {
+ ON_MAIN_THREAD(
+ setMinMaxSize(app);
+ );
+ }
+}
+
+void SetMaxWindowSize(struct Application *app, int maxWidth, int maxHeight)
+{
+ // Guard against calling during shutdown
+ if( app->shuttingDown ) return;
+
+ app->maxWidth = maxWidth;
+ app->maxHeight = maxHeight;
+
+ // Apply if the window is created
+ if( app->mainWindow != NULL ) {
+ ON_MAIN_THREAD(
+ setMinMaxSize(app);
+ );
+ }
+}
+
+
+void SetDebug(void *applicationPointer, int flag) {
+ debug = flag;
+}
+
+
+
+// AddContextMenu sets the context menu map for this application
+void AddContextMenu(struct Application *app, const char *contextMenuJSON) {
+ // Guard against calling during shutdown
+ if( app->shuttingDown ) return;
+ ON_MAIN_THREAD (
+ AddContextMenuToStore(app->contextMenuStore, contextMenuJSON);
+ );
+}
+
+void UpdateContextMenu(struct Application *app, const char* contextMenuJSON) {
+ // Guard against calling during shutdown
+ if( app->shuttingDown ) return;
+ ON_MAIN_THREAD(
+ UpdateContextMenuInStore(app->contextMenuStore, contextMenuJSON);
+ );
+}
+
+void AddTrayMenu(struct Application *app, const char *trayMenuJSON) {
+ // Guard against calling during shutdown
+ if( app->shuttingDown ) return;
+
+ ON_MAIN_THREAD(
+ AddTrayMenuToStore(TrayMenuStoreSingleton, trayMenuJSON);
+ );
+}
+
+void SetTrayMenu(struct Application *app, const char* trayMenuJSON) {
+
+ // Guard against calling during shutdown
+ if( app->shuttingDown ) return;
+
+ ON_MAIN_THREAD(
+ UpdateTrayMenuInStore(TrayMenuStoreSingleton, trayMenuJSON);
+ );
+}
+
+void DeleteTrayMenuByID(struct Application *app, const char *id) {
+ ON_MAIN_THREAD(
+ DeleteTrayMenuInStore(TrayMenuStoreSingleton, id);
+ );
+}
+
+void UpdateTrayMenuLabel(struct Application* app, const char* JSON) {
+ // Guard against calling during shutdown
+ if( app->shuttingDown ) return;
+
+ ON_MAIN_THREAD(
+ UpdateTrayMenuLabelInStore(TrayMenuStoreSingleton, JSON);
+ );
+}
+
+
+void SetBindings(struct Application *app, const char *bindings) {
+ const char* temp = concat("window.wailsbindings = \"", bindings);
+ const char* jscall = concat(temp, "\";");
+ MEMFREE(temp);
+ app->bindings = jscall;
+}
+
+void makeWindowBackgroundTranslucent(struct Application *app) {
+ id contentView = msg_reg(app->mainWindow, s("contentView"));
+ id effectView = msg_reg(c("NSVisualEffectView"), s("alloc"));
+ CGRect bounds = GET_BOUNDS(contentView);
+ effectView = ((id(*)(id, SEL, CGRect))objc_msgSend)(effectView, s("initWithFrame:"), bounds);
+
+ msg_int(effectView, s("setAutoresizingMask:"), NSViewWidthSizable | NSViewHeightSizable);
+ msg_int(effectView, s("setBlendingMode:"), NSVisualEffectBlendingModeBehindWindow);
+ msg_int(effectView, s("setState:"), NSVisualEffectStateActive);
+ ((id(*)(id, SEL, id, int, id))objc_msgSend)(contentView, s("addSubview:positioned:relativeTo:"), effectView, NSWindowBelow, NULL);
+}
+
+void enableBoolConfig(id config, const char *setting) {
+ ((id(*)(id, SEL, id, id))objc_msgSend)(msg_reg(config, s("preferences")), s("setValue:forKey:"), msg_bool(c("NSNumber"), s("numberWithBool:"), 1), str(setting));
+}
+
+void disableBoolConfig(id config, const char *setting) {
+ ((id(*)(id, SEL, id, id))objc_msgSend)(msg_reg(config, s("preferences")), s("setValue:forKey:"), msg_bool(c("NSNumber"), s("numberWithBool:"), 0), str(setting));
+}
+
+void processDecorations(struct Application *app) {
+
+ int decorations = 0;
+
+ if (app->frame == 1 ) {
+ if( app->hideTitleBar == 0) {
+ decorations |= NSWindowStyleMaskTitled;
+ }
+ decorations |= NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable;
+ }
+
+ if (app->resizable) {
+ decorations |= NSWindowStyleMaskResizable;
+ }
+
+ if (app->fullscreen) {
+ decorations |= NSWindowStyleMaskFullscreen;
+ }
+
+ if( app->fullSizeContent || app->frame == 0) {
+ decorations |= NSWindowStyleMaskFullSizeContentView;
+ }
+
+ app->decorations = decorations;
+}
+
+void createApplication(struct Application *app) {
+ id application = msg_reg(c("NSApplication"), s("sharedApplication"));
+ app->application = application;
+ msg_int(application, s("setActivationPolicy:"), app->activationPolicy);
+}
+
+void DarkModeEnabled(struct Application *app, const char *callbackID) {
+ // Guard against calling during shutdown
+ if( app->shuttingDown ) return;
+
+ ON_MAIN_THREAD(
+ const char *result = isDarkMode(app) ? "T" : "F";
+
+ // Construct callback message. Format "SD|"
+ const char *callback = concat("SD", callbackID);
+ const char *header = concat(callback, "|");
+ const char *responseMessage = concat(header, result);
+ // Send message to backend
+ app->sendMessageToBackend(responseMessage);
+
+ // Free memory
+ MEMFREE(header);
+ MEMFREE(callback);
+ MEMFREE(responseMessage);
+ );
+}
+
+void getURL(id self, SEL selector, id event, id replyEvent) {
+ struct Application *app = (struct Application *)objc_getAssociatedObject(self, "application");
+ id desc = msg_int(event, s("paramDescriptorForKeyword:"), keyDirectObject);
+ id url = msg_reg(desc, s("stringValue"));
+ const char* curl = cstr(url);
+ if( curl == NULL ) {
+ return;
+ }
+
+ // If this was an incoming URL, but we aren't running yet
+ // save it to return when we complete
+ if( app->running != true ) {
+ app->startupURL = STRCOPY(curl);
+ return;
+ }
+
+ const char* message = concat("UC", curl);
+ messageFromWindowCallback(message);
+ MEMFREE(message);
+}
+
+void openURLs(id self, SEL selector, id event) {
+ filelog("\n\nI AM HERE!!!!!\n\n");
+}
+
+
+void createDelegate(struct Application *app) {
+
+ // Define delegate
+ Class appDelegate = objc_allocateClassPair((Class) c("NSResponder"), "AppDelegate", 0);
+ class_addProtocol(appDelegate, objc_getProtocol("NSTouchBarProvider"));
+
+ class_addMethod(appDelegate, s("applicationShouldTerminateAfterLastWindowClosed:"), (IMP) no, "c@:@");
+ class_addMethod(appDelegate, s("applicationWillFinishLaunching:"), (IMP) willFinishLaunching, "v@:@");
+
+ // All Menu Items use a common callback
+ class_addMethod(appDelegate, s("menuItemCallback:"), (IMP)menuItemCallback, "v@:@");
+
+ // If there are URL Handlers, register the callback method
+ if( app->hasURLHandlers ) {
+ class_addMethod(appDelegate, s("getUrl:withReplyEvent:"), (IMP) getURL, "i@:@@");
+ }
+
+ // Script handler
+ class_addMethod(appDelegate, s("userContentController:didReceiveScriptMessage:"), (IMP) messageHandler, "v@:@@");
+ objc_registerClassPair(appDelegate);
+
+ // Create delegate
+ id delegate = msg_reg((id)appDelegate, s("new"));
+ objc_setAssociatedObject(delegate, "application", (id)app, OBJC_ASSOCIATION_ASSIGN);
+
+ // Theme change listener
+ class_addMethod(appDelegate, s("themeChanged:"), (IMP) themeChanged, "v@:@@");
+
+ // Get defaultCenter
+ id defaultCenter = msg_reg(c("NSDistributedNotificationCenter"), s("defaultCenter"));
+ ((id(*)(id, SEL, id, SEL, id, id))objc_msgSend)(defaultCenter, s("addObserver:selector:name:object:"), delegate, s("themeChanged:"), str("AppleInterfaceThemeChangedNotification"), NULL);
+
+ app->delegate = delegate;
+
+ msg_id(app->application, s("setDelegate:"), delegate);
+}
+
+bool windowShouldClose(id self, SEL cmd, id sender) {
+ msg_reg(sender, s("orderOut:"));
+ return false;
+}
+
+bool windowShouldExit(id self, SEL cmd, id sender) {
+ msg_reg(sender, s("orderOut:"));
+ messageFromWindowCallback("WC");
+ return false;
+}
+
+void createMainWindow(struct Application *app) {
+ // Create main window
+ id mainWindow = ALLOC("NSWindow");
+ mainWindow = ((id(*)(id, SEL, CGRect, int, int, BOOL))objc_msgSend)(mainWindow, s("initWithContentRect:styleMask:backing:defer:"),
+ CGRectMake(0, 0, app->width, app->height), app->decorations, NSBackingStoreBuffered, NO);
+ msg_reg(mainWindow, s("autorelease"));
+
+ // Set Appearance
+ if( app->appearance != NULL ) {
+ msg_id(mainWindow, s("setAppearance:"),
+ msg_id(c("NSAppearance"), s("appearanceNamed:"), str(app->appearance))
+ );
+ }
+
+ // Set Title appearance
+ msg_bool(mainWindow, s("setTitlebarAppearsTransparent:"), app->titlebarAppearsTransparent ? YES : NO);
+ msg_int(mainWindow, s("setTitleVisibility:"), app->hideTitle);
+
+ // Create window delegate to override windowShouldClose
+ Class delegateClass = objc_allocateClassPair((Class) c("NSObject"), "WindowDelegate", 0);
+ bool resultAddProtoc = class_addProtocol(delegateClass, objc_getProtocol("NSWindowDelegate"));
+ if( app->hideWindowOnClose ) {
+ class_replaceMethod(delegateClass, s("windowShouldClose:"), (IMP) windowShouldClose, "v@:@");
+ } else {
+ class_replaceMethod(delegateClass, s("windowShouldClose:"), (IMP) windowShouldExit, "v@:@");
+ }
+ app->windowDelegate = msg_reg((id)delegateClass, s("new"));
+ msg_id(mainWindow, s("setDelegate:"), app->windowDelegate);
+
+ app->mainWindow = mainWindow;
+}
+
+const char* getInitialState(struct Application *app) {
+ const char *result = "";
+ if( isDarkMode(app) ) {
+ result = "window.wails.System.IsDarkMode.set(true);";
+ } else {
+ result = "window.wails.System.IsDarkMode.set(false);";
+ }
+ char buffer[999];
+ snprintf(&buffer[0], sizeof(buffer), "window.wails.System.LogLevel.set(%d);", app->logLevel);
+ result = concat(result, &buffer[0]);
+ Debug(app, "initialstate = %s", result);
+ return result;
+}
+
+void parseMenuRole(struct Application *app, id parentMenu, JsonNode *item) {
+ const char *roleName = item->string_;
+
+ if ( STREQ(roleName, "appMenu") ) {
+ createDefaultAppMenu(parentMenu);
+ return;
+ }
+ if ( STREQ(roleName, "editMenu")) {
+ createDefaultEditMenu(parentMenu);
+ return;
+ }
+ if ( STREQ(roleName, "hide")) {
+ addMenuItem(parentMenu, "Hide Window", "hide:", "h", FALSE);
+ return;
+ }
+ if ( STREQ(roleName, "hideothers")) {
+ id hideOthers = addMenuItem(parentMenu, "Hide Others", "hideOtherApplications:", "h", FALSE);
+ msg_int(hideOthers, s("setKeyEquivalentModifierMask:"), (NSEventModifierFlagOption | NSEventModifierFlagCommand));
+ return;
+ }
+ if ( STREQ(roleName, "unhide")) {
+ addMenuItem(parentMenu, "Show All", "unhideAllApplications:", "", FALSE);
+ return;
+ }
+ if ( STREQ(roleName, "front")) {
+ addMenuItem(parentMenu, "Bring All to Front", "arrangeInFront:", "", FALSE);
+ return;
+ }
+ if ( STREQ(roleName, "undo")) {
+ addMenuItem(parentMenu, "Undo", "undo:", "z", FALSE);
+ return;
+ }
+ if ( STREQ(roleName, "redo")) {
+ addMenuItem(parentMenu, "Redo", "redo:", "y", FALSE);
+ return;
+ }
+ if ( STREQ(roleName, "cut")) {
+ addMenuItem(parentMenu, "Cut", "cut:", "x", FALSE);
+ return;
+ }
+ if ( STREQ(roleName, "copy")) {
+ addMenuItem(parentMenu, "Copy", "copy:", "c", FALSE);
+ return;
+ }
+ if ( STREQ(roleName, "paste")) {
+ addMenuItem(parentMenu, "Paste", "paste:", "v", FALSE);
+ return;
+ }
+ if ( STREQ(roleName, "delete")) {
+ addMenuItem(parentMenu, "Delete", "delete:", "", FALSE);
+ return;
+ }
+ if( STREQ(roleName, "pasteandmatchstyle")) {
+ id pasteandmatchstyle = addMenuItem(parentMenu, "Paste and Match Style", "pasteandmatchstyle:", "v", FALSE);
+ msg_int(pasteandmatchstyle, s("setKeyEquivalentModifierMask:"), (NSEventModifierFlagOption | NSEventModifierFlagShift | NSEventModifierFlagCommand));
+ }
+ if ( STREQ(roleName, "selectall")) {
+ addMenuItem(parentMenu, "Select All", "selectAll:", "a", FALSE);
+ return;
+ }
+ if ( STREQ(roleName, "minimize")) {
+ addMenuItem(parentMenu, "Minimize", "miniaturize:", "m", FALSE);
+ return;
+ }
+ if ( STREQ(roleName, "zoom")) {
+ addMenuItem(parentMenu, "Zoom", "performZoom:", "", FALSE);
+ return;
+ }
+ if ( STREQ(roleName, "quit")) {
+ addMenuItem(parentMenu, "Quit", "terminate:", "q", FALSE);
+ return;
+ }
+ if ( STREQ(roleName, "togglefullscreen")) {
+ addMenuItem(parentMenu, "Toggle Full Screen", "toggleFullScreen:", "f", FALSE);
+ return;
+ }
+
+}
+
+void dumpMemberList(const char *name, id *memberList) {
+ void *member = memberList[0];
+ int count = 0;
+ printf("%s = %p -> [ ", name, memberList);
+ while( member != NULL ) {
+ printf("%p ", member);
+ count = count + 1;
+ member = memberList[count];
+ }
+ printf("]\n");
+}
+
+// updateMenu replaces the current menu with the given one
+void updateMenu(struct Application *app, const char *menuAsJSON) {
+ Debug(app, "Menu is now: %s", menuAsJSON);
+ ON_MAIN_THREAD (
+ DeleteMenu(app->applicationMenu);
+ Menu* newMenu = NewApplicationMenu(menuAsJSON);
+ id menu = GetMenu(newMenu);
+ app->applicationMenu = newMenu;
+ msg_id(msg_reg(c("NSApplication"), s("sharedApplication")), s("setMainMenu:"), menu);
+ );
+}
+
+// SetApplicationMenu sets the initial menu for the application
+void SetApplicationMenu(struct Application *app, const char *menuAsJSON) {
+ // Guard against calling during shutdown
+ if( app->shuttingDown ) return;
+
+ if ( app->applicationMenu == NULL ) {
+ app->applicationMenu = NewApplicationMenu(menuAsJSON);
+ return;
+ }
+
+ // Update menu
+ ON_MAIN_THREAD (
+ updateMenu(app, menuAsJSON);
+ );
+}
+
+void processDialogIcons(struct hashmap_s *hashmap, const unsigned char *dialogIcons[]) {
+
+ unsigned int count = 0;
+ while( 1 ) {
+ const unsigned char *name = dialogIcons[count++];
+ if( name == 0x00 ) {
+ break;
+ }
+ const unsigned char *lengthAsString = dialogIcons[count++];
+ if( name == 0x00 ) {
+ break;
+ }
+ const unsigned char *data = dialogIcons[count++];
+ if( data == 0x00 ) {
+ break;
+ }
+ int length = atoi((const char *)lengthAsString);
+
+ // Create the icon and add to the hashmap
+ id imageData = ((id(*)(id, SEL, const unsigned char *, int))objc_msgSend)(c("NSData"), s("dataWithBytes:length:"), data, length);
+ id dialogImage = ALLOC("NSImage");
+ msg_reg(dialogImage, s("autorelease"));
+ msg_id(dialogImage, s("initWithData:"), imageData);
+ hashmap_put(hashmap, (const char *)name, strlen((const char *)name), dialogImage);
+ }
+
+}
+
+void processUserDialogIcons(struct Application *app) {
+
+ // Allocate the Dialog icon hashmap
+ if( 0 != hashmap_create((const unsigned)4, &dialogIconCache)) {
+ // Couldn't allocate map
+ Fatal(app, "Not enough memory to allocate dialogIconCache!");
+ return;
+ }
+
+ processDialogIcons(&dialogIconCache, defaultDialogIcons);
+ processDialogIcons(&dialogIconCache, userDialogIcons);
+
+}
+
+void TrayMenuWillOpen(id self, SEL selector, id menu) {
+ // Extract tray menu id from menu
+ id trayMenuIDStr = objc_getAssociatedObject(menu, "trayMenuID");
+ const char* trayMenuID = cstr(trayMenuIDStr);
+ const char *message = concat("Mo", trayMenuID);
+ messageFromWindowCallback(message);
+ MEMFREE(message);
+}
+
+void TrayMenuDidClose(id self, SEL selector, id menu) {
+ // Extract tray menu id from menu
+ id trayMenuIDStr = objc_getAssociatedObject(menu, "trayMenuID");
+ const char* trayMenuID = cstr(trayMenuIDStr);
+ const char *message = concat("Mc", trayMenuID);
+ messageFromWindowCallback(message);
+ MEMFREE(message);
+}
+
+void createTrayMenuDelegate() {
+ // Define delegate
+ trayMenuDelegateClass = objc_allocateClassPair((Class) c("NSObject"), "MenuDelegate", 0);
+ class_addProtocol(trayMenuDelegateClass, objc_getProtocol("NSMenuDelegate"));
+ class_addMethod(trayMenuDelegateClass, s("menuWillOpen:"), (IMP) TrayMenuWillOpen, "v@:@");
+ class_addMethod(trayMenuDelegateClass, s("menuDidClose:"), (IMP) TrayMenuDidClose, "v@:@");
+
+ // Script handler
+ objc_registerClassPair(trayMenuDelegateClass);
+}
+
+
+void Run(struct Application *app, int argc, char **argv) {
+
+ // Process window decorations
+ processDecorations(app);
+
+ // Create the application
+ createApplication(app);
+
+ // Define delegate
+ createDelegate(app);
+
+ // Define tray delegate
+ createTrayMenuDelegate();
+
+ // Create the main window
+ createMainWindow(app);
+
+ // Create Content View
+ id contentView = msg_reg( ALLOC("NSView"), s("init") );
+ msg_id(app->mainWindow, s("setContentView:"), contentView);
+
+ // Set the main window title
+ SetTitle(app, app->title);
+
+ // Center Window
+ Center(app);
+
+ // Set Colour
+ applyWindowColour(app);
+
+ // Process translucency
+ if (app->WindowIsTranslucent) {
+ makeWindowBackgroundTranslucent(app);
+ }
+
+ // We set it to be invisible by default. It will become visible when everything has initialised
+ msg_bool(app->mainWindow, s("setIsVisible:"), NO);
+
+ // Setup webview
+ id config = msg_reg(c("WKWebViewConfiguration"), s("new"));
+ ((id(*)(id, SEL, id, id))objc_msgSend)(config, s("setValue:forKey:"), msg_bool(c("NSNumber"), s("numberWithBool:"), 1), str("suppressesIncrementalRendering"));
+ if (app->devtools) {
+ Debug(app, "Enabling devtools");
+ enableBoolConfig(config, "developerExtrasEnabled");
+ }
+ app->config = config;
+
+ id manager = msg_reg(config, s("userContentController"));
+ msg_id_id(manager, s("addScriptMessageHandler:name:"), app->delegate, str("external"));
+ msg_id_id(manager, s("addScriptMessageHandler:name:"), app->delegate, str("completed"));
+ msg_id_id(manager, s("addScriptMessageHandler:name:"), app->delegate, str("error"));
+ app->manager = manager;
+
+ id wkwebview = msg_reg(c("WKWebView"), s("alloc"));
+ app->wkwebview = wkwebview;
+
+ ((id(*)(id, SEL, CGRect, id))objc_msgSend)(wkwebview, s("initWithFrame:configuration:"), CGRectMake(0, 0, 0, 0), config);
+
+ msg_id(contentView, s("addSubview:"), wkwebview);
+ msg_int(wkwebview, s("setAutoresizingMask:"), NSViewWidthSizable | NSViewHeightSizable);
+ CGRect contentViewBounds = GET_BOUNDS(contentView);
+ ((id(*)(id, SEL, CGRect))objc_msgSend)(wkwebview, s("setFrame:"), contentViewBounds );
+
+ // Disable damn smart quotes
+ // Credit: https://stackoverflow.com/a/31640511
+ id userDefaults = msg_reg(c("NSUserDefaults"), s("standardUserDefaults"));
+ ((id(*)(id, SEL, BOOL, id))objc_msgSend)(userDefaults, s("setBool:forKey:"), false, str("NSAutomaticQuoteSubstitutionEnabled"));
+
+ // Setup drag message handler
+ msg_id_id(manager, s("addScriptMessageHandler:name:"), app->delegate, str("windowDrag"));
+ // Add mouse event hooks
+ app->mouseDownMonitor = ((id(*)(id, SEL, int, id (^)(id)))objc_msgSend)(c("NSEvent"), u("addLocalMonitorForEventsMatchingMask:handler:"), NSEventMaskLeftMouseDown, ^(id incomingEvent) {
+ // Make sure the mouse click was in the window, not the tray
+ id window = msg_reg(incomingEvent, s("window"));
+ if (window == app->mainWindow) {
+ app->mouseEvent = incomingEvent;
+ }
+ return incomingEvent;
+ });
+ app->mouseUpMonitor = ((id(*)(id, SEL, int, id (^)(id)))objc_msgSend)(c("NSEvent"), u("addLocalMonitorForEventsMatchingMask:handler:"), NSEventMaskLeftMouseUp, ^(id incomingEvent) {
+ app->mouseEvent = NULL;
+ ShowMouse();
+ return incomingEvent;
+ });
+
+ // Setup context menu message handler
+ msg_id_id(manager, s("addScriptMessageHandler:name:"), app->delegate, str("contextMenu"));
+
+ // Toolbar
+ if( app->useToolBar ) {
+ Debug(app, "Setting Toolbar");
+ id toolbar = msg_reg(c("NSToolbar"),s("alloc"));
+ msg_id(toolbar, s("initWithIdentifier:"), str("wails.toolbar"));
+ msg_reg(toolbar, s("autorelease"));
+
+ // Separator
+ if( app->hideToolbarSeparator ) {
+ msg_bool(toolbar, s("setShowsBaselineSeparator:"), NO);
+ }
+
+ msg_id(app->mainWindow, s("setToolbar:"), toolbar);
+ }
+
+ // Fix up resizing
+ if (app->resizable == 0) {
+ app->minHeight = app->maxHeight = app->height;
+ app->minWidth = app->maxWidth = app->width;
+ }
+ setMinMaxSize(app);
+
+ // Load HTML
+ id html = msg_id(c("NSURL"), s("URLWithString:"), str((const char*)assets[0]));
+ msg_id(wkwebview, s("loadRequest:"), msg_id(c("NSURLRequest"), s("requestWithURL:"), html));
+
+ Debug(app, "Loading Internal Code");
+ // We want to evaluate the internal code plus runtime before the assets
+ const char *temp = concat(invoke, app->bindings);
+ const char *internalCode = concat(temp, (const char*)&runtime);
+ MEMFREE(temp);
+
+ // Add code that sets up the initial state, EG: State Stores.
+ const char *initialState = getInitialState(app);
+ temp = concat(internalCode, initialState);
+ MEMFREE(initialState);
+ MEMFREE(internalCode);
+ internalCode = temp;
+
+ // Loop over assets and build up one giant Mother Of All Evals
+ int index = 1;
+ while(1) {
+ // Get next asset pointer
+ const unsigned char *asset = assets[index];
+
+ // If we have no more assets, break
+ if (asset == 0x00) {
+ break;
+ }
+
+ temp = concat(internalCode, (const char *)asset);
+ MEMFREE(internalCode);
+ internalCode = temp;
+ index++;
+ };
+
+ // Disable context menu if not in debug mode
+ if( debug != 1 ) {
+ temp = concat(internalCode, "wails._.DisableDefaultContextMenu();");
+ MEMFREE(internalCode);
+ internalCode = temp;
+ }
+
+ // class_addMethod(delegateClass, s("applicationWillFinishLaunching:"), (IMP) willFinishLaunching, "@@:@");
+ // Include callback after evaluation
+ temp = concat(internalCode, "webkit.messageHandlers.completed.postMessage(true);");
+ MEMFREE(internalCode);
+ internalCode = temp;
+
+ // const char *viewportScriptString = "var meta = document.createElement('meta'); meta.setAttribute('name', 'viewport'); meta.setAttribute('content', 'width=device-width'); meta.setAttribute('initial-scale', '1.0'); meta.setAttribute('maximum-scale', '1.0'); meta.setAttribute('minimum-scale', '1.0'); meta.setAttribute('user-scalable', 'no'); document.getElementsByTagName('head')[0].appendChild(meta);";
+ // ExecJS(app, viewportScriptString);
+
+
+ // This evaluates the MOAE once the Dom has finished loading
+ msg_id(manager,
+ s("addUserScript:"),
+ ((id(*)(id, SEL, id, int, int))objc_msgSend)(msg_reg(c("WKUserScript"), s("alloc")),
+ s("initWithSource:injectionTime:forMainFrameOnly:"),
+ str(internalCode),
+ 1,
+ 1));
+
+
+ // Emit theme change event to notify of current system them
+ emitThemeChange(app);
+
+ // If we want the webview to be transparent...
+ if( app->webviewIsTranparent == 1 ) {
+ ((id(*)(id, SEL, id, id))objc_msgSend)(wkwebview, s("setValue:forKey:"), msg_bool(c("NSNumber"), s("numberWithBool:"), 0), str("drawsBackground"));
+ }
+
+ // If we have an application menu, process it
+ if( app->applicationMenu != NULL ) {
+ id menu = GetMenu(app->applicationMenu);
+ msg_id(msg_reg(c("NSApplication"), s("sharedApplication")), s("setMainMenu:"), menu);
+ }
+
+ // Setup initial trays
+ ShowTrayMenusInStore(TrayMenuStoreSingleton);
+
+ // Process dialog icons
+ processUserDialogIcons(app);
+
+ // Finally call run
+ Debug(app, "Run called");
+ msg_reg(app->application, s("run"));
+
+ DestroyApplication(app);
+
+ MEMFREE(internalCode);
+}
+
+void SetActivationPolicy(struct Application* app, int policy) {
+ app->activationPolicy = policy;
+}
+
+void HasURLHandlers(struct Application* app) {
+ app->hasURLHandlers = 1;
+}
+
+// Quit will stop the cocoa application and free up all the memory
+// used by the application
+void Quit(struct Application *app) {
+ Debug(app, "Quit Called");
+ msg_id(app->application, s("stop:"), NULL);
+}
+
+id createImageFromBase64Data(const char *data, bool isTemplateImage) {
+ id nsdata = ALLOC("NSData");
+ id imageData = ((id(*)(id, SEL, id, int))objc_msgSend)(nsdata, s("initWithBase64EncodedString:options:"), str(data), 0);
+
+ // If it's not valid base64 data, use the broken image
+ if ( imageData == NULL ) {
+ imageData = ((id(*)(id, SEL, id, int))objc_msgSend)(nsdata, s("initWithBase64EncodedString:options:"), str(BrokenImage), 0);
+ }
+ id result = ALLOC("NSImage");
+ msg_reg(result, s("autorelease"));
+ msg_id(result, s("initWithData:"), imageData);
+ msg_reg(nsdata, s("release"));
+ msg_reg(imageData, s("release"));
+
+ if( isTemplateImage ) {
+ msg_bool(result, s("setTemplate:"), YES);
+ }
+
+ return result;
+}
+
+void* NewApplication(const char *title, int width, int height, int resizable, int devtools, int fullscreen, int startHidden, int logLevel, int hideWindowOnClose) {
+
+ // Load the tray icons
+ LoadTrayIcons();
+
+ // Setup main application struct
+ struct Application *result = malloc(sizeof(struct Application));
+ result->title = title;
+ result->width = width;
+ result->height = height;
+ result->minWidth = 0;
+ result->minHeight = 0;
+ result->maxWidth = 0;
+ result->maxHeight = 0;
+ result->resizable = resizable;
+ result->devtools = devtools;
+ result->fullscreen = fullscreen;
+ result->maximised = 0;
+ result->startHidden = startHidden;
+ result->decorations = 0;
+ result->logLevel = logLevel;
+ result->hideWindowOnClose = hideWindowOnClose;
+
+ result->mainWindow = NULL;
+ result->mouseEvent = NULL;
+ result->mouseDownMonitor = NULL;
+ result->mouseUpMonitor = NULL;
+
+ // Features
+ result->frame = 1;
+ result->hideTitle = 0;
+ result->hideTitleBar = 0;
+ result->fullSizeContent = 0;
+ result->useToolBar = 0;
+ result->hideToolbarSeparator = 0;
+ result->appearance = NULL;
+ result->WindowIsTranslucent = 0;
+
+ // Window data
+ result->delegate = NULL;
+
+ // Menu
+ result->applicationMenu = NULL;
+
+ // Tray
+ TrayMenuStoreSingleton = NewTrayMenuStore();
+
+ // Context Menus
+ result->contextMenuStore = NewContextMenuStore();
+
+ // Window delegate
+ result->windowDelegate = NULL;
+
+ // Window Appearance
+ result->titlebarAppearsTransparent = 0;
+ result->webviewIsTranparent = 0;
+
+ result->sendMessageToBackend = (ffenestriCallback) messageFromWindowCallback;
+
+ result->shuttingDown = false;
+
+ result->activationPolicy = NSApplicationActivationPolicyRegular;
+
+ result->hasURLHandlers = 0;
+
+ result->startupURL = NULL;
+
+ result->running = false;
+
+ result->pool = msg_reg(c("NSAutoreleasePool"), s("new"));
+
+ return (void*) result;
+}
+
+
+#endif
diff --git a/v2/internal/ffenestri/ffenestri_darwin.go b/v2/internal/ffenestri/ffenestri_darwin.go
new file mode 100644
index 000000000..02d7471b1
--- /dev/null
+++ b/v2/internal/ffenestri/ffenestri_darwin.go
@@ -0,0 +1,99 @@
+package ffenestri
+
+/*
+#cgo darwin CFLAGS: -DFFENESTRI_DARWIN=1
+#cgo darwin LDFLAGS: -framework WebKit -framework CoreFoundation -lobjc
+
+#include "ffenestri.h"
+#include "ffenestri_darwin.h"
+
+*/
+import "C"
+
+func (a *Application) processPlatformSettings() error {
+
+ mac := a.config.Mac
+ titlebar := mac.TitleBar
+
+ // HideTitle
+ if titlebar.HideTitle {
+ C.HideTitle(a.app)
+ }
+
+ // HideTitleBar
+ if titlebar.HideTitleBar {
+ C.HideTitleBar(a.app)
+ }
+
+ // Full Size Content
+ if titlebar.FullSizeContent {
+ C.FullSizeContent(a.app)
+ }
+
+ // Toolbar
+ if titlebar.UseToolbar {
+ C.UseToolbar(a.app)
+ }
+
+ if titlebar.HideToolbarSeparator {
+ C.HideToolbarSeparator(a.app)
+ }
+
+ if titlebar.TitlebarAppearsTransparent {
+ C.TitlebarAppearsTransparent(a.app)
+ }
+
+ // Process window Appearance
+ if mac.Appearance != "" {
+ C.SetAppearance(a.app, a.string2CString(string(mac.Appearance)))
+ }
+
+ // Set activation policy
+ C.SetActivationPolicy(a.app, C.int(mac.ActivationPolicy))
+
+ // Check if the webview should be transparent
+ if mac.WebviewIsTransparent {
+ C.WebviewIsTransparent(a.app)
+ }
+
+ // Check if window should be translucent
+ if mac.WindowIsTranslucent {
+ C.WindowIsTranslucent(a.app)
+ }
+
+ // Process menu
+ //applicationMenu := options.GetApplicationMenu(a.config)
+ applicationMenu := a.menuManager.GetApplicationMenuJSON()
+ if applicationMenu != "" {
+ C.SetApplicationMenu(a.app, a.string2CString(applicationMenu))
+ }
+
+ // Process tray
+ trays, err := a.menuManager.GetTrayMenus()
+ if err != nil {
+ return err
+ }
+ if trays != nil {
+ for _, tray := range trays {
+ C.AddTrayMenu(a.app, a.string2CString(tray))
+ }
+ }
+
+ // Process context menus
+ contextMenus, err := a.menuManager.GetContextMenus()
+ if err != nil {
+ return err
+ }
+ if contextMenus != nil {
+ for _, contextMenu := range contextMenus {
+ C.AddContextMenu(a.app, a.string2CString(contextMenu))
+ }
+ }
+
+ // Process URL Handlers
+ if a.config.Mac.URLHandlers != nil {
+ C.HasURLHandlers(a.app)
+ }
+
+ return nil
+}
diff --git a/v2/internal/ffenestri/ffenestri_darwin.h b/v2/internal/ffenestri/ffenestri_darwin.h
new file mode 100644
index 000000000..fd00338a4
--- /dev/null
+++ b/v2/internal/ffenestri/ffenestri_darwin.h
@@ -0,0 +1,154 @@
+
+#ifndef FFENESTRI_DARWIN_H
+#define FFENESTRI_DARWIN_H
+
+
+#define OBJC_OLD_DISPATCH_PROTOTYPES 1
+#include
+#include
+#include
+#include "json.h"
+#include "hashmap.h"
+#include "stdlib.h"
+
+typedef struct {
+ long maj;
+ long min;
+ long patch;
+} OSVersion;
+
+// Macros to make it slightly more sane
+#define msg objc_msgSend
+#define msg_reg ((id(*)(id, SEL))objc_msgSend)
+#define msg_id ((id(*)(id, SEL, id))objc_msgSend)
+#define msg_id_id ((id(*)(id, SEL, id, id))objc_msgSend)
+#define msg_bool ((id(*)(id, SEL, BOOL))objc_msgSend)
+#define msg_int ((id(*)(id, SEL, int))objc_msgSend)
+#define msg_uint ((id(*)(id, SEL, unsigned int))objc_msgSend)
+#define msg_float ((id(*)(id, SEL, float))objc_msgSend)
+#define kInternetEventClass 'GURL'
+#define kAEGetURL 'GURL'
+#define keyDirectObject '----'
+
+#define c(str) (id)objc_getClass(str)
+#define s(str) sel_registerName(str)
+#define u(str) sel_getUid(str)
+#define str(input) ((id(*)(id, SEL, const char *))objc_msgSend)(c("NSString"), s("stringWithUTF8String:"), input)
+#define strunicode(input) ((id(*)(id, SEL, id, unsigned short))objc_msgSend)(c("NSString"), s("stringWithFormat:"), str("%C"), (unsigned short)input)
+#define cstr(input) (const char *)msg_reg(input, s("UTF8String"))
+#define url(input) msg_id(c("NSURL"), s("fileURLWithPath:"), str(input))
+#define ALLOC(classname) msg_reg(c(classname), s("alloc"))
+#define ALLOC_INIT(classname) msg_reg(msg_reg(c(classname), s("alloc")), s("init"))
+
+#if defined (__aarch64__)
+#define GET_FRAME(receiver) ((CGRect(*)(id, SEL))objc_msgSend)(receiver, s("frame"))
+#define GET_BOUNDS(receiver) ((CGRect(*)(id, SEL))objc_msgSend)(receiver, s("bounds"))
+#define GET_OSVERSION(receiver) ((OSVersion(*)(id, SEL))objc_msgSend)(processInfo, s("operatingSystemVersion"));
+#endif
+
+#if defined (__x86_64__)
+#define GET_FRAME(receiver) ((CGRect(*)(id, SEL))objc_msgSend_stret)(receiver, s("frame"))
+#define GET_BOUNDS(receiver) ((CGRect(*)(id, SEL))objc_msgSend_stret)(receiver, s("bounds"))
+#define GET_OSVERSION(receiver) ((OSVersion(*)(id, SEL))objc_msgSend_stret)(processInfo, s("operatingSystemVersion"));
+#endif
+
+#define GET_BACKINGSCALEFACTOR(receiver) ((CGFloat(*)(id, SEL))objc_msgSend)(receiver, s("backingScaleFactor"))
+
+#define ON_MAIN_THREAD(str) dispatch( ^{ str; } )
+#define MAIN_WINDOW_CALL(str) msg_reg(app->mainWindow, s((str)))
+
+#define NSBackingStoreBuffered 2
+
+#define NSWindowStyleMaskBorderless 0
+#define NSWindowStyleMaskTitled 1
+#define NSWindowStyleMaskClosable 2
+#define NSWindowStyleMaskMiniaturizable 4
+#define NSWindowStyleMaskResizable 8
+#define NSWindowStyleMaskFullscreen 1 << 14
+
+#define NSVisualEffectMaterialWindowBackground 12
+#define NSVisualEffectBlendingModeBehindWindow 0
+#define NSVisualEffectStateFollowsWindowActiveState 0
+#define NSVisualEffectStateActive 1
+#define NSVisualEffectStateInactive 2
+
+#define NSViewWidthSizable 2
+#define NSViewHeightSizable 16
+
+#define NSWindowBelow -1
+#define NSWindowAbove 1
+
+#define NSSquareStatusItemLength -2.0
+#define NSVariableStatusItemLength -1.0
+
+#define NSWindowTitleHidden 1
+#define NSWindowStyleMaskFullSizeContentView 1 << 15
+
+#define NSEventModifierFlagCommand 1 << 20
+#define NSEventModifierFlagOption 1 << 19
+#define NSEventModifierFlagControl 1 << 18
+#define NSEventModifierFlagShift 1 << 17
+
+#define NSControlStateValueMixed -1
+#define NSControlStateValueOff 0
+#define NSControlStateValueOn 1
+
+#define NSApplicationActivationPolicyRegular 0
+#define NSApplicationActivationPolicyAccessory 1
+#define NSApplicationActivationPolicyProhibited 2
+
+// Unbelievably, if the user swaps their button preference
+// then right buttons are reported as left buttons
+#define NSEventMaskLeftMouseDown 1 << 1
+#define NSEventMaskLeftMouseUp 1 << 2
+#define NSEventMaskRightMouseDown 1 << 3
+#define NSEventMaskRightMouseUp 1 << 4
+
+#define NSEventTypeLeftMouseDown 1
+#define NSEventTypeLeftMouseUp 2
+#define NSEventTypeRightMouseDown 3
+#define NSEventTypeRightMouseUp 4
+
+#define NSNoImage 0
+#define NSImageOnly 1
+#define NSImageLeft 2
+#define NSImageRight 3
+#define NSImageBelow 4
+#define NSImageAbove 5
+#define NSImageOverlaps 6
+
+#define NSAlertStyleWarning 0
+#define NSAlertStyleInformational 1
+#define NSAlertStyleCritical 2
+
+#define NSAlertFirstButtonReturn 1000
+#define NSAlertSecondButtonReturn 1001
+#define NSAlertThirdButtonReturn 1002
+
+#define BrokenImage "iVBORw0KGgoAAAANSUhEUgAAABAAAAASCAMAAABl5a5YAAABj1BMVEWopan///+koqSWk5P9/v3///////////+AgACMiovz8/PB0fG9z+3i4+WysbGBfX1Erh80rACLiYqBxolEsDhHlDEbqQDDx+CNho7W1tj4+/bw+O3P5Mn4/f/W1tbK6sX////b2dn////////////8/Pz6+vro6Ojj4+P////G1PL////EzNydmp2cmZnd3eDF1PHs8v/o8P/Q3vrS3vfE0vCdmpqZkpr19/3N2vXI1vPH1fOgnqDg6frP3PbCytvHx8irqq6HhIZtuGtjnlZetU1Xs0NWskBNsi7w9v/d6P7w9P3S4Pzr8Pvl7PrY5PrU4PjQ3fjD1Ozo6Om30NjGzNi7ubm34K+UxKmbnaWXlJeUjpSPi4tppF1TtjxSsTf2+f7L2PTr7e3H2+3V7+q+0uXg4OPg4eLR1uG7z+Hg4ODGzODV2N7V1trP5dmxzs65vcfFxMWq0cKxxr+/vr+0s7apxbWaxrCv2qao05+dlp2Uuo2Dn4F8vIB6xnyAoHmAym9zqGpctENLryNFsgoblJpnAAAAKnRSTlP+hP7+5ZRmYgL+/f39/f39/f38/Pz8/Pv69+7j083My8GocnBPTTMWEgjxeITOAAABEklEQVQY0y3KZXuCYBiG4ceYuu7u3nyVAaKOMBBQ7O5Yd3f3fvheDnd9u8/jBkGwNxP6sjOWVQvY/ftrzfT6bd3yEhCnYZqiaYoKiwX/gXkFiHySTcUTLJMsZ9v8nQvgssWYOEKedKpcOO6CUXD5IlGEY5hLUbyDAAZ6HRf1bnkoavOsFQibg+Q4nuNYL+ON5PHD5nBaraRVyxnzGf6BJzUi2QQCQgMyk8tleL7dg1owpJ17D5IkvV100EingeOopPyo6vfAuXF+9hbDTknZCIaUoeK4efKwG4iT6xDewd7imGlid7gGwv37b6Oh9jwaTdOf/Tc1qH7UZVmuP6G5qZfBr9cAGNy4KiDd4tXIs7tS+QO9aUKvPAIKuQAAAABJRU5ErkJggg=="
+
+struct Application;
+int releaseNSObject(void *const context, struct hashmap_element_s *const e);
+void TitlebarAppearsTransparent(struct Application* app);
+void HideTitle(struct Application* app);
+void HideTitleBar(struct Application* app);
+void FullSizeContent(struct Application* app);
+void UseToolbar(struct Application* app);
+void HideToolbarSeparator(struct Application* app);
+void DisableFrame(struct Application* app);
+void SetAppearance(struct Application* app, const char *);
+void WebviewIsTransparent(struct Application* app);
+void WindowIsTranslucent(struct Application* app);
+void SetTray(struct Application* app, const char *, const char *, const char *);
+//void SetContextMenus(struct Application* app, const char *);
+void AddTrayMenu(struct Application* app, const char *);
+
+void SetActivationPolicy(struct Application* app, int policy);
+
+void* lookupStringConstant(id constantName);
+
+void HasURLHandlers(struct Application* app);
+
+id createImageFromBase64Data(const char *data, bool isTemplateImage);
+
+#endif
\ No newline at end of file
diff --git a/v2/internal/ffenestri/ffenestri_linux.c b/v2/internal/ffenestri/ffenestri_linux.c
new file mode 100644
index 000000000..ab6b6032b
--- /dev/null
+++ b/v2/internal/ffenestri/ffenestri_linux.c
@@ -0,0 +1,995 @@
+
+#ifndef __FFENESTRI_LINUX_H__
+#define __FFENESTRI_LINUX_H__
+
+#include "common.h"
+#include "gtk/gtk.h"
+#include "webkit2/webkit2.h"
+#include
+#include
+#include
+#include
+#include
+
+// References to assets
+extern const unsigned char runtime;
+
+#include "icon.h"
+#include "assets.h"
+
+// Constants
+#define PRIMARY_MOUSE_BUTTON 1
+#define MIDDLE_MOUSE_BUTTON 2
+#define SECONDARY_MOUSE_BUTTON 3
+
+// MAIN DEBUG FLAG
+int debug;
+
+// Debug works like sprintf but mutes if the global debug flag is true
+// Credit: https://stackoverflow.com/a/20639708
+void Debug(char *message, ...)
+{
+ if (debug)
+ {
+ char *temp = concat("TRACE | Ffenestri (C) | ", message);
+ message = concat(temp, "\n");
+ free(temp);
+ va_list args;
+ va_start(args, message);
+ vprintf(message, args);
+ free(message);
+ va_end(args);
+ }
+}
+
+extern void messageFromWindowCallback(const char *);
+typedef void (*ffenestriCallback)(const char *);
+
+struct Application
+{
+
+ // Gtk Data
+ GtkApplication *application;
+ GtkWindow *mainWindow;
+ GtkWidget *webView;
+ int signalInvoke;
+ int signalWindowDrag;
+ int signalButtonPressed;
+ int signalButtonReleased;
+ int signalLoadChanged;
+
+ // Saves the events for the drag mouse button
+ GdkEventButton *dragButtonEvent;
+
+ // The number of the default drag button
+ int dragButton;
+
+ // Window Data
+ const char *title;
+ char *id;
+ int width;
+ int height;
+ int resizable;
+ int devtools;
+ int startHidden;
+ int fullscreen;
+ int minWidth;
+ int minHeight;
+ int maxWidth;
+ int maxHeight;
+ int frame;
+
+ // User Data
+ char *HTML;
+
+ // Callback
+ ffenestriCallback sendMessageToBackend;
+
+ // Bindings
+ const char *bindings;
+
+ // Lock - used for sync operations (Should we be using g_mutex?)
+ int lock;
+};
+
+void *NewApplication(const char *title, int width, int height, int resizable, int devtools, int fullscreen, int startHidden)
+{
+ // Setup main application struct
+ struct Application *result = malloc(sizeof(struct Application));
+ result->title = title;
+ result->width = width;
+ result->height = height;
+ result->resizable = resizable;
+ result->devtools = devtools;
+ result->fullscreen = fullscreen;
+ result->minWidth = 0;
+ result->minHeight = 0;
+ result->maxWidth = 0;
+ result->maxHeight = 0;
+ result->frame = 1;
+ result->startHidden = startHidden;
+
+ // Default drag button is PRIMARY
+ result->dragButton = PRIMARY_MOUSE_BUTTON;
+
+ result->sendMessageToBackend = (ffenestriCallback)messageFromWindowCallback;
+
+ // Create a unique ID based on the current unix timestamp
+ char temp[11];
+ sprintf(&temp[0], "%d", (int)time(NULL));
+ result->id = concat("wails.app", &temp[0]);
+
+ // Create the main GTK application
+ GApplicationFlags flags = G_APPLICATION_FLAGS_NONE;
+ result->application = gtk_application_new(result->id, flags);
+
+ // Return the application struct
+ return (void *)result;
+}
+
+void DestroyApplication(struct Application *app)
+{
+ Debug("Destroying Application");
+
+ g_application_quit(G_APPLICATION(app->application));
+
+ // Release the GTK ID string
+ if (app->id != NULL)
+ {
+ free(app->id);
+ app->id = NULL;
+ }
+ else
+ {
+ Debug("Almost a double free for app->id");
+ }
+
+ // Free the bindings
+ if (app->bindings != NULL)
+ {
+ free((void *)app->bindings);
+ app->bindings = NULL;
+ }
+ else
+ {
+ Debug("Almost a double free for app->bindings");
+ }
+
+ // Disconnect signal handlers
+ WebKitUserContentManager *manager = webkit_web_view_get_user_content_manager((WebKitWebView *)app->webView);
+ g_signal_handler_disconnect(manager, app->signalInvoke);
+ if( app->frame == 0) {
+ g_signal_handler_disconnect(manager, app->signalWindowDrag);
+ g_signal_handler_disconnect(app->webView, app->signalButtonPressed);
+ g_signal_handler_disconnect(app->webView, app->signalButtonReleased);
+ }
+ g_signal_handler_disconnect(app->webView, app->signalLoadChanged);
+
+ // Release the main GTK Application
+ if (app->application != NULL)
+ {
+ g_object_unref(app->application);
+ app->application = NULL;
+ }
+ else
+ {
+ Debug("Almost a double free for app->application");
+ }
+ Debug("Finished Destroying Application");
+}
+
+// Quit will stop the gtk application and free up all the memory
+// used by the application
+void Quit(struct Application *app)
+{
+ Debug("Quit Called");
+ gtk_window_close((GtkWindow *)app->mainWindow);
+ g_application_quit((GApplication *)app->application);
+ DestroyApplication(app);
+}
+
+// SetTitle sets the main window title to the given string
+void SetTitle(struct Application *app, const char *title)
+{
+ gtk_window_set_title(app->mainWindow, title);
+}
+
+// Fullscreen sets the main window to be fullscreen
+void Fullscreen(struct Application *app)
+{
+ gtk_window_fullscreen(app->mainWindow);
+}
+
+// UnFullscreen resets the main window after a fullscreen
+void UnFullscreen(struct Application *app)
+{
+ gtk_window_unfullscreen(app->mainWindow);
+}
+
+void setMinMaxSize(struct Application *app)
+{
+ GdkGeometry size;
+ size.min_width = size.min_height = size.max_width = size.max_height = 0;
+ int flags = 0;
+ if (app->maxHeight > 0 && app->maxWidth > 0)
+ {
+ size.max_height = app->maxHeight;
+ size.max_width = app->maxWidth;
+ flags |= GDK_HINT_MAX_SIZE;
+ }
+ if (app->minHeight > 0 && app->minWidth > 0)
+ {
+ size.min_height = app->minHeight;
+ size.min_width = app->minWidth;
+ flags |= GDK_HINT_MIN_SIZE;
+ }
+ gtk_window_set_geometry_hints(app->mainWindow, NULL, &size, flags);
+}
+
+char *fileDialogInternal(struct Application *app, GtkFileChooserAction chooserAction, char **args) {
+ GtkFileChooserNative *native;
+ GtkFileChooserAction action = chooserAction;
+ gint res;
+ char *filename;
+
+ char *title = args[0];
+ char *filter = args[1];
+
+ native = gtk_file_chooser_native_new(title,
+ app->mainWindow,
+ action,
+ "_Open",
+ "_Cancel");
+
+ GtkFileChooser *chooser = GTK_FILE_CHOOSER(native);
+
+ // If we have filters, process them
+ if (filter[0] != '\0') {
+ GtkFileFilter *file_filter = gtk_file_filter_new();
+ gchar **filters = g_strsplit(filter, ",", -1);
+ gint i;
+ for(i = 0; filters && filters[i]; i++) {
+ gtk_file_filter_add_pattern(file_filter, filters[i]);
+ // Debug("Adding filter pattern: %s\n", filters[i]);
+ }
+ gtk_file_filter_set_name(file_filter, filter);
+ gtk_file_chooser_add_filter(chooser, file_filter);
+ g_strfreev(filters);
+ }
+
+ res = gtk_native_dialog_run(GTK_NATIVE_DIALOG(native));
+ if (res == GTK_RESPONSE_ACCEPT)
+ {
+ filename = gtk_file_chooser_get_filename(chooser);
+ }
+
+ g_object_unref(native);
+
+ return filename;
+}
+
+// openFileDialogInternal opens a dialog to select a file
+// NOTE: The result is a string that will need to be freed!
+char *openFileDialogInternal(struct Application *app, char **args)
+{
+ return fileDialogInternal(app, GTK_FILE_CHOOSER_ACTION_OPEN, args);
+}
+
+// saveFileDialogInternal opens a dialog to select a file
+// NOTE: The result is a string that will need to be freed!
+char *saveFileDialogInternal(struct Application *app, char **args)
+{
+ return fileDialogInternal(app, GTK_FILE_CHOOSER_ACTION_SAVE, args);
+}
+
+
+// openDirectoryDialogInternal opens a dialog to select a directory
+// NOTE: The result is a string that will need to be freed!
+char *openDirectoryDialogInternal(struct Application *app, char **args)
+{
+ return fileDialogInternal(app, GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER, args);
+}
+
+void SetMinWindowSize(struct Application *app, int minWidth, int minHeight)
+{
+ app->minWidth = minWidth;
+ app->minHeight = minHeight;
+}
+
+void SetMaxWindowSize(struct Application *app, int maxWidth, int maxHeight)
+{
+ app->maxWidth = maxWidth;
+ app->maxHeight = maxHeight;
+}
+
+// SetColour sets the colour of the webview to the given colour string
+void SetColour(struct Application *app, int red, int green, int blue, int alpha)
+{
+// GdkRGBA rgba;
+// rgba.
+// gboolean result = gdk_rgba_parse(&rgba, colourString);
+// if (result == FALSE)
+// {
+// return 0;
+// }
+// // Debug("Setting webview colour to: %s", colourString);
+// webkit_web_view_get_background_color((WebKitWebView *)(app->webView), &rgba);
+}
+
+// DisableFrame disables the window frame
+void DisableFrame(struct Application *app)
+{
+ app->frame = 0;
+}
+
+void syncCallback(GObject *source_object,
+ GAsyncResult *res,
+ void *data)
+{
+ struct Application *app = (struct Application *)data;
+ app->lock = 0;
+}
+
+void syncEval(struct Application *app, const gchar *script)
+{
+
+ WebKitWebView *webView = (WebKitWebView *)(app->webView);
+
+ // wait for lock to free
+ while (app->lock == 1)
+ {
+ g_main_context_iteration(0, true);
+ }
+ // Set lock
+ app->lock = 1;
+
+ webkit_web_view_run_javascript(
+ webView,
+ script,
+ NULL, syncCallback, (void*)app);
+
+ while (app->lock == 1)
+ {
+ g_main_context_iteration(0, true);
+ }
+}
+
+void asyncEval(WebKitWebView *webView, const gchar *script)
+{
+ webkit_web_view_run_javascript(
+ webView,
+ script,
+ NULL, NULL, NULL);
+}
+
+typedef void (*dispatchMethod)(struct Application *app, void *);
+
+struct dispatchData
+{
+ struct Application *app;
+ dispatchMethod method;
+ void *args;
+};
+
+gboolean executeMethod(gpointer data)
+{
+ struct dispatchData *d = (struct dispatchData *)data;
+ (d->method)(d->app, d->args);
+ g_free(d);
+ return FALSE;
+}
+
+void ExecJS(struct Application *app, char *js)
+{
+ struct dispatchData *data = (struct dispatchData *)g_new(struct dispatchData, 1);
+ data->method = (dispatchMethod)syncEval;
+ data->args = js;
+ data->app = app;
+
+ gdk_threads_add_idle(executeMethod, data);
+}
+
+typedef char *(*dialogMethod)(struct Application *app, void *);
+
+struct dialogCall
+{
+ struct Application *app;
+ dialogMethod method;
+ void *args;
+ void *filter;
+ char *result;
+ int done;
+};
+
+gboolean executeMethodWithReturn(gpointer data)
+{
+ struct dialogCall *d = (struct dialogCall *)data;
+
+ d->result = (d->method)(d->app, d->args);
+ d->done = 1;
+ return FALSE;
+}
+
+char *OpenFileDialog(struct Application *app, char *title, char *filter)
+{
+ struct dialogCall *data = (struct dialogCall *)g_new(struct dialogCall, 1);
+ data->result = NULL;
+ data->done = 0;
+ data->method = (dialogMethod)openFileDialogInternal;
+ const char* dialogArgs[]={ title, filter };
+ data->args = dialogArgs;
+ data->app = app;
+
+ gdk_threads_add_idle(executeMethodWithReturn, data);
+
+ while (data->done == 0)
+ {
+ usleep(100000);
+ }
+ g_free(data);
+ return data->result;
+}
+
+char *SaveFileDialog(struct Application *app, char *title, char *filter)
+{
+ struct dialogCall *data = (struct dialogCall *)g_new(struct dialogCall, 1);
+ data->result = NULL;
+ data->done = 0;
+ data->method = (dialogMethod)saveFileDialogInternal;
+ const char* dialogArgs[]={ title, filter };
+ data->args = dialogArgs;
+ data->app = app;
+
+ gdk_threads_add_idle(executeMethodWithReturn, data);
+
+ while (data->done == 0)
+ {
+ usleep(100000);
+ }
+ Debug("Dialog done");
+ Debug("Result = %s\n", data->result);
+
+ g_free(data);
+ // Fingers crossed this wasn't freed by g_free above
+ return data->result;
+}
+
+char *OpenDirectoryDialog(struct Application *app, char *title, char *filter)
+{
+ struct dialogCall *data = (struct dialogCall *)g_new(struct dialogCall, 1);
+ data->result = NULL;
+ data->done = 0;
+ data->method = (dialogMethod)openDirectoryDialogInternal;
+ const char* dialogArgs[]={ title, filter };
+ data->args = dialogArgs;
+ data->app = app;
+
+ gdk_threads_add_idle(executeMethodWithReturn, data);
+
+ while (data->done == 0)
+ {
+ usleep(100000);
+ }
+ Debug("Directory Dialog done");
+ Debug("Result = %s\n", data->result);
+ g_free(data);
+ // Fingers crossed this wasn't freed by g_free above
+ return data->result;
+}
+
+// Sets the icon to the XPM stored in icon
+void setIcon(struct Application *app)
+{
+ GdkPixbuf *appIcon = gdk_pixbuf_new_from_xpm_data((const char **)icon);
+ gtk_window_set_icon(app->mainWindow, appIcon);
+}
+
+static void load_finished_cb(WebKitWebView *webView,
+ WebKitLoadEvent load_event,
+ struct Application *app)
+{
+ switch (load_event)
+ {
+ // case WEBKIT_LOAD_STARTED:
+ // /* New load, we have now a provisional URI */
+ // // printf("Start downloading %s\n", webkit_web_view_get_uri(web_view));
+ // /* Here we could start a spinner or update the
+ // * location bar with the provisional URI */
+ // break;
+ // case WEBKIT_LOAD_REDIRECTED:
+ // // printf("Redirected to: %s\n", webkit_web_view_get_uri(web_view));
+ // break;
+ // case WEBKIT_LOAD_COMMITTED:
+ // /* The load is being performed. Current URI is
+ // * the final one and it won't change unless a new
+ // * load is requested or a navigation within the
+ // * same page is performed */
+ // // printf("Loading: %s\n", webkit_web_view_get_uri(web_view));
+ // break;
+ case WEBKIT_LOAD_FINISHED:
+ /* Load finished, we can now stop the spinner */
+ // printf("Finished loading: %s\n", webkit_web_view_get_uri(web_view));
+
+ // Bindings
+ Debug("Binding Methods");
+ syncEval(app, app->bindings);
+
+ // Setup IPC commands
+ Debug("Setting up IPC methods");
+ const char *invoke = "window.wailsInvoke=function(message){window.webkit.messageHandlers.external.postMessage(message);};window.wailsDrag=function(message){window.webkit.messageHandlers.windowDrag.postMessage(message);};window.wailsContextMenuMessage=function(message){window.webkit.messageHandlers.contextMenu.postMessage(message);};";
+ syncEval(app, invoke);
+
+ // Runtime
+ Debug("Setting up Wails runtime");
+ syncEval(app, &runtime);
+
+ // Loop over assets
+ int index = 1;
+ while (1)
+ {
+ // Get next asset pointer
+ const char *asset = assets[index];
+
+ // If we have no more assets, break
+ if (asset == 0x00)
+ {
+ break;
+ }
+
+ // sync eval the asset
+ syncEval(app, asset);
+ index++;
+ };
+
+ // Set the icon
+ setIcon(app);
+
+ // Setup fullscreen
+ if (app->fullscreen)
+ {
+ Debug("Going fullscreen");
+ Fullscreen(app);
+ }
+
+ // Setup resize
+ gtk_window_resize(GTK_WINDOW(app->mainWindow), app->width, app->height);
+
+ if (app->resizable)
+ {
+ gtk_window_set_default_size(GTK_WINDOW(app->mainWindow), app->width, app->height);
+ }
+ else
+ {
+ gtk_widget_set_size_request(GTK_WIDGET(app->mainWindow), app->width, app->height);
+ gtk_window_resize(GTK_WINDOW(app->mainWindow), app->width, app->height);
+ // Fix the min/max to the window size for good measure
+ app->minHeight = app->maxHeight = app->height;
+ app->minWidth = app->maxWidth = app->width;
+ }
+ gtk_window_set_resizable(GTK_WINDOW(app->mainWindow), app->resizable ? TRUE : FALSE);
+ setMinMaxSize(app);
+
+ // Centre by default
+ gtk_window_set_position(app->mainWindow, GTK_WIN_POS_CENTER);
+
+ // Show window and focus
+ if( app->startHidden == 0) {
+ gtk_widget_show_all(GTK_WIDGET(app->mainWindow));
+ gtk_widget_grab_focus(app->webView);
+ }
+ break;
+ }
+}
+
+static gboolean disable_context_menu_cb(
+ WebKitWebView *web_view,
+ WebKitContextMenu *context_menu,
+ GdkEvent *event,
+ WebKitHitTestResult *hit_test_result,
+ gpointer user_data)
+{
+ return TRUE;
+}
+
+static void printEvent(const char *message, GdkEventButton *event)
+{
+ Debug("%s: [button:%d] [x:%f] [y:%f] [time:%d]",
+ message,
+ event->button,
+ event->x_root,
+ event->y_root,
+ event->time);
+}
+
+
+static void dragWindow(WebKitUserContentManager *contentManager,
+ WebKitJavascriptResult *result,
+ struct Application *app)
+{
+ // If we get this message erroneously, ignore
+ if (app->dragButtonEvent == NULL)
+ {
+ return;
+ }
+
+ // Ignore non-toplevel widgets
+ GtkWidget *window = gtk_widget_get_toplevel(GTK_WIDGET(app->webView));
+ if (!GTK_IS_WINDOW(window))
+ {
+ return;
+ }
+
+ // Initiate the drag
+ printEvent("Starting drag with event", app->dragButtonEvent);
+
+ gtk_window_begin_move_drag(app->mainWindow,
+ app->dragButton,
+ app->dragButtonEvent->x_root,
+ app->dragButtonEvent->y_root,
+ app->dragButtonEvent->time);
+ // Clear the event
+ app->dragButtonEvent = NULL;
+
+ return;
+}
+
+gboolean buttonPress(GtkWidget *widget, GdkEventButton *event, struct Application *app)
+{
+ if (event->type == GDK_BUTTON_PRESS && event->button == app->dragButton)
+ {
+ app->dragButtonEvent = event;
+ }
+ return FALSE;
+}
+
+gboolean buttonRelease(GtkWidget *widget, GdkEventButton *event, struct Application *app)
+{
+ if (event->type == GDK_BUTTON_RELEASE && event->button == app->dragButton)
+ {
+ app->dragButtonEvent = NULL;
+ }
+ return FALSE;
+}
+
+static void sendMessageToBackend(WebKitUserContentManager *contentManager,
+ WebKitJavascriptResult *result,
+ struct Application *app)
+{
+#if WEBKIT_MAJOR_VERSION >= 2 && WEBKIT_MINOR_VERSION >= 22
+ JSCValue *value = webkit_javascript_result_get_js_value(result);
+ char *message = jsc_value_to_string(value);
+#else
+ JSGlobalContextRef context = webkit_javascript_result_get_global_context(result);
+ JSValueRef value = webkit_javascript_result_get_value(result);
+ JSStringRef js = JSValueToStringCopy(context, value, NULL);
+ size_t messageSize = JSStringGetMaximumUTF8CStringSize(js);
+ char *message = g_new(char, messageSize);
+ JSStringGetUTF8CString(js, message, messageSize);
+ JSStringRelease(js);
+#endif
+ app->sendMessageToBackend(message);
+ g_free(message);
+}
+
+void SetDebug(struct Application *app, int flag)
+{
+ debug = flag;
+}
+
+// getCurrentMonitorGeometry gets the geometry of the monitor
+// that the window is mostly on.
+GdkRectangle getCurrentMonitorGeometry(GtkWindow *window) {
+ // Get the monitor that the window is currently on
+ GdkDisplay *display = gtk_widget_get_display(GTK_WIDGET(window));
+ GdkWindow *gdk_window = gtk_widget_get_window(GTK_WIDGET(window));
+ GdkMonitor *monitor = gdk_display_get_monitor_at_window (display, gdk_window);
+
+ // Get the geometry of the monitor
+ GdkRectangle result;
+ gdk_monitor_get_geometry (monitor,&result);
+
+ return result;
+}
+
+/*******************
+ * Window Position *
+ *******************/
+
+// Position holds an x/y corrdinate
+struct Position {
+ int x;
+ int y;
+};
+
+// Internal call for setting the position of the window.
+void setPositionInternal(struct Application *app, struct Position *pos) {
+
+ // Get the monitor geometry
+ GdkRectangle m = getCurrentMonitorGeometry(app->mainWindow);
+
+ // Move the window relative to the monitor
+ gtk_window_move(app->mainWindow, m.x + pos->x, m.y + pos->y);
+
+ // Free memory
+ free(pos);
+}
+
+// SetPosition sets the position of the window to the given x/y
+// coordinates. The x/y values are relative to the monitor
+// the window is mostly on.
+void SetPosition(struct Application *app, int x, int y) {
+ struct dispatchData *data = (struct dispatchData *)g_new(struct dispatchData, 1);
+ data->method = (dispatchMethod)setPositionInternal;
+ struct Position *pos = malloc(sizeof(struct Position));
+ pos->x = x;
+ pos->y = y;
+ data->args = pos;
+ data->app = app;
+
+ gdk_threads_add_idle(executeMethod, data);
+}
+
+/***************
+ * Window Size *
+ ***************/
+
+// Size holds a width/height
+struct Size {
+ int width;
+ int height;
+};
+
+// Internal call for setting the size of the window.
+void setSizeInternal(struct Application *app, struct Size *size) {
+ gtk_window_resize(app->mainWindow, size->width, size->height);
+ free(size);
+}
+
+// SetSize sets the size of the window to the given width/height
+void SetSize(struct Application *app, int width, int height) {
+ struct dispatchData *data = (struct dispatchData *)g_new(struct dispatchData, 1);
+ data->method = (dispatchMethod)setSizeInternal;
+ struct Size *size = malloc(sizeof(struct Size));
+ size->width = width;
+ size->height = height;
+ data->args = size;
+ data->app = app;
+
+ gdk_threads_add_idle(executeMethod, data);
+}
+
+
+// centerInternal will center the main window on the monitor it is mostly in
+void centerInternal(struct Application *app)
+{
+ // Get the geometry of the monitor
+ GdkRectangle m = getCurrentMonitorGeometry(app->mainWindow);
+
+ // Get the window width/height
+ int windowWidth, windowHeight;
+ gtk_window_get_size(app->mainWindow, &windowWidth, &windowHeight);
+
+ // Place the window at the center of the monitor
+ gtk_window_move(app->mainWindow, ((m.width - windowWidth) / 2) + m.x, ((m.height - windowHeight) / 2) + m.y);
+}
+
+// Center the window
+void Center(struct Application *app) {
+
+ // Setup a call to centerInternal on the main thread
+ struct dispatchData *data = (struct dispatchData *)g_new(struct dispatchData, 1);
+ data->method = (dispatchMethod)centerInternal;
+ data->app = app;
+
+ // Add call to main thread
+ gdk_threads_add_idle(executeMethod, data);
+}
+
+// hideInternal hides the main window
+void hideInternal(struct Application *app) {
+ gtk_widget_hide (GTK_WIDGET(app->mainWindow));
+}
+
+// Hide places the hideInternal method onto the main thread for execution
+void Hide(struct Application *app) {
+
+ // Setup a call to hideInternal on the main thread
+ struct dispatchData *data = (struct dispatchData *)g_new(struct dispatchData, 1);
+ data->method = (dispatchMethod)hideInternal;
+ data->app = app;
+
+ // Add call to main thread
+ gdk_threads_add_idle(executeMethod, data);
+}
+
+// showInternal shows the main window
+void showInternal(struct Application *app) {
+ gtk_widget_show_all(GTK_WIDGET(app->mainWindow));
+ gtk_widget_grab_focus(app->webView);
+}
+
+// Show places the showInternal method onto the main thread for execution
+void Show(struct Application *app) {
+ struct dispatchData *data = (struct dispatchData *)g_new(struct dispatchData, 1);
+ data->method = (dispatchMethod)showInternal;
+ data->app = app;
+
+ gdk_threads_add_idle(executeMethod, data);
+}
+
+
+// maximiseInternal maximises the main window
+void maximiseInternal(struct Application *app) {
+ gtk_window_maximize(GTK_WINDOW(app->mainWindow));
+}
+
+// Maximise places the maximiseInternal method onto the main thread for execution
+void Maximise(struct Application *app) {
+
+ // Setup a call to maximiseInternal on the main thread
+ struct dispatchData *data = (struct dispatchData *)g_new(struct dispatchData, 1);
+ data->method = (dispatchMethod)maximiseInternal;
+ data->app = app;
+
+ // Add call to main thread
+ gdk_threads_add_idle(executeMethod, data);
+}
+
+// unmaximiseInternal unmaximises the main window
+void unmaximiseInternal(struct Application *app) {
+ gtk_window_unmaximize(GTK_WINDOW(app->mainWindow));
+}
+
+// Unmaximise places the unmaximiseInternal method onto the main thread for execution
+void Unmaximise(struct Application *app) {
+
+ // Setup a call to unmaximiseInternal on the main thread
+ struct dispatchData *data = (struct dispatchData *)g_new(struct dispatchData, 1);
+ data->method = (dispatchMethod)unmaximiseInternal;
+ data->app = app;
+
+ // Add call to main thread
+ gdk_threads_add_idle(executeMethod, data);
+}
+
+
+void DarkModeEnabled(struct Application* app, char *callbackID) {}
+void SetApplicationMenu(struct Application* app, const char *menuJSON) {}
+void AddTrayMenu(struct Application* app, const char *menuTrayJSON) {}
+void SetTrayMenu(struct Application* app, const char *menuTrayJSON) {}
+void DeleteTrayMenuByID(struct Application* app, const char *id) {}
+void UpdateTrayMenuLabel(struct Application* app, const char* JSON) {}
+void AddContextMenu(struct Application* app, char *contextMenuJSON) {}
+void UpdateContextMenu(struct Application* app, char *contextMenuJSON) {}
+void WebviewIsTransparent(struct Application* app) {}
+void WindowIsTranslucent(struct Application* app) {}
+void OpenDialog(struct Application* app, char *callbackID, char *title, char *filters, char *defaultFilename, char *defaultDir, int allowFiles, int allowDirs, int allowMultiple, int showHiddenFiles, int canCreateDirectories, int resolvesAliases, int treatPackagesAsDirectories) {}
+void SaveDialog(struct Application* app, char *callbackID, char *title, char *filters, char *defaultFilename, char *defaultDir, int showHiddenFiles, int canCreateDirectories, int treatPackagesAsDirectories) {}
+void MessageDialog(struct Application* app, char *callbackID, char *type, char *title, char *message, char *icon, char *button1, char *button2, char *button3, char *button4, char *defaultButton, char *cancelButton) {}
+
+
+// minimiseInternal minimises the main window
+void minimiseInternal(struct Application *app) {
+ gtk_window_iconify(app->mainWindow);
+}
+
+// Minimise places the minimiseInternal method onto the main thread for execution
+void Minimise(struct Application *app) {
+
+ // Setup a call to minimiseInternal on the main thread
+ struct dispatchData *data = (struct dispatchData *)g_new(struct dispatchData, 1);
+ data->method = (dispatchMethod)minimiseInternal;
+ data->app = app;
+
+ // Add call to main thread
+ gdk_threads_add_idle(executeMethod, data);
+}
+
+// unminimiseInternal unminimises the main window
+void unminimiseInternal(struct Application *app) {
+ gtk_window_present(app->mainWindow);
+}
+
+// Unminimise places the unminimiseInternal method onto the main thread for execution
+void Unminimise(struct Application *app) {
+
+ // Setup a call to unminimiseInternal on the main thread
+ struct dispatchData *data = (struct dispatchData *)g_new(struct dispatchData, 1);
+ data->method = (dispatchMethod)unminimiseInternal;
+ data->app = app;
+
+ // Add call to main thread
+ gdk_threads_add_idle(executeMethod, data);
+}
+
+
+void SetBindings(struct Application *app, const char *bindings)
+{
+ const char *temp = concat("window.wailsbindings = \"", bindings);
+ const char *jscall = concat(temp, "\";");
+ free((void *)temp);
+ app->bindings = jscall;
+}
+
+// This is called when the close button on the window is pressed
+gboolean close_button_pressed(GtkWidget *widget,
+ GdkEvent *event,
+ struct Application *app)
+{
+ app->sendMessageToBackend("WC"); // Window Close
+ return TRUE;
+}
+
+static void setupWindow(struct Application *app)
+{
+
+ // Create the window
+ GtkWidget *mainWindow = gtk_application_window_new(app->application);
+ // Save reference
+ app->mainWindow = GTK_WINDOW(mainWindow);
+
+ // Setup frame
+ gtk_window_set_decorated((GtkWindow *)mainWindow, app->frame);
+
+ // Setup title
+ gtk_window_set_title(GTK_WINDOW(mainWindow), app->title);
+
+ // Setup script handler
+ WebKitUserContentManager *contentManager = webkit_user_content_manager_new();
+
+ // Setup the invoke handler
+ webkit_user_content_manager_register_script_message_handler(contentManager, "external");
+ app->signalInvoke = g_signal_connect(contentManager, "script-message-received::external", G_CALLBACK(sendMessageToBackend), app);
+
+ // Setup the window drag handler if this is a frameless app
+ if ( app->frame == 0 ) {
+ webkit_user_content_manager_register_script_message_handler(contentManager, "windowDrag");
+ app->signalWindowDrag = g_signal_connect(contentManager, "script-message-received::windowDrag", G_CALLBACK(dragWindow), app);
+ // Setup the mouse handlers
+ app->signalButtonPressed = g_signal_connect(app->webView, "button-press-event", G_CALLBACK(buttonPress), app);
+ app->signalButtonReleased = g_signal_connect(app->webView, "button-release-event", G_CALLBACK(buttonRelease), app);
+ }
+ GtkWidget *webView = webkit_web_view_new_with_user_content_manager(contentManager);
+
+ // Save reference
+ app->webView = webView;
+
+ // Add the webview to the window
+ gtk_container_add(GTK_CONTAINER(mainWindow), webView);
+
+
+ // Load default HTML
+ app->signalLoadChanged = g_signal_connect(G_OBJECT(webView), "load-changed", G_CALLBACK(load_finished_cb), app);
+
+ // Load the user's HTML
+ // assets[0] is the HTML because the asset array is bundled like that by convention
+ webkit_web_view_load_uri(WEBKIT_WEB_VIEW(webView), assets[0]);
+
+ // Check if we want to enable the dev tools
+ if (app->devtools)
+ {
+ WebKitSettings *settings = webkit_web_view_get_settings(WEBKIT_WEB_VIEW(webView));
+ // webkit_settings_set_enable_write_console_messages_to_stdout(settings, true);
+ webkit_settings_set_enable_developer_extras(settings, true);
+ }
+ else
+ {
+ g_signal_connect(G_OBJECT(webView), "context-menu", G_CALLBACK(disable_context_menu_cb), app);
+ }
+
+ // Listen for close button signal
+ g_signal_connect(GTK_WIDGET(mainWindow), "delete-event", G_CALLBACK(close_button_pressed), app);
+}
+
+static void activate(GtkApplication* _, struct Application *app)
+{
+ setupWindow(app);
+}
+
+void Run(struct Application *app, int argc, char **argv)
+{
+ g_signal_connect(app->application, "activate", G_CALLBACK(activate), app);
+ g_application_run(G_APPLICATION(app->application), argc, argv);
+}
+
+#endif
diff --git a/v2/internal/ffenestri/ffenestri_linux.go b/v2/internal/ffenestri/ffenestri_linux.go
new file mode 100644
index 000000000..ca7abe7a1
--- /dev/null
+++ b/v2/internal/ffenestri/ffenestri_linux.go
@@ -0,0 +1,17 @@
+package ffenestri
+
+/*
+#cgo linux CFLAGS: -DFFENESTRI_LINUX=1
+#cgo linux pkg-config: gtk+-3.0 webkit2gtk-4.0
+
+
+#include "ffenestri.h"
+#include "ffenestri_linux.h"
+
+*/
+import "C"
+
+func (a *Application) processPlatformSettings() error {
+
+ return nil
+}
diff --git a/v2/internal/ffenestri/ffenestri_linux.h b/v2/internal/ffenestri/ffenestri_linux.h
new file mode 100644
index 000000000..26902d334
--- /dev/null
+++ b/v2/internal/ffenestri/ffenestri_linux.h
@@ -0,0 +1,6 @@
+
+#ifndef FFENESTRI_LINUX_H
+#define FFENESTRI_LINUX_H
+
+
+#endif
\ No newline at end of file
diff --git a/v2/internal/ffenestri/ffenestri_windows.cpp b/v2/internal/ffenestri/ffenestri_windows.cpp
new file mode 100644
index 000000000..91500774f
--- /dev/null
+++ b/v2/internal/ffenestri/ffenestri_windows.cpp
@@ -0,0 +1,906 @@
+// Some code may be inspired by or directly used from Webview (c) zserge.
+// License included in README.md
+
+#include "ffenestri_windows.h"
+#include "shellscalingapi.h"
+#include "wv2ComHandler_windows.h"
+#include
+#include
+#include
+#include
+#include
+#include "windows/WebView2.h"
+#include
+#include "effectstructs_windows.h"
+#include
+
+int debug = 0;
+DWORD mainThread;
+
+#define WS_EX_NOREDIRECTIONBITMAP 0x00200000L
+
+// --- Assets
+extern const unsigned char runtime;
+extern const unsigned char *defaultDialogIcons[];
+
+// dispatch will execute the given `func` pointer
+void dispatch(dispatchFunction func) {
+ PostThreadMessage(mainThread, WM_APP, 0, (LPARAM) new dispatchFunction(func));
+}
+
+void processKeyPress(UINT key) {
+ // Get state of Control
+ bool controlPressed = GetKeyState(VK_CONTROL) >> 15 != 0;
+ bool altPressed = GetKeyState(VK_MENU) >> 15 != 0;
+ bool shiftPressed = GetKeyState(VK_SHIFT) >> 15 != 0;
+
+ // Save the modifier keys
+ BYTE modState = 0;
+ if ( GetKeyState(VK_CONTROL) >> 15 != 0 ) { modState |= 1; }
+ if ( GetKeyState(VK_MENU) >> 15 != 0 ) { modState |= 2; }
+ if ( GetKeyState(VK_SHIFT) >> 15 != 0 ) { modState |= 4; }
+ if ( GetKeyState(VK_LWIN) >> 15 != 0 ) { modState |= 8; }
+ if ( GetKeyState(VK_RWIN) >> 15 != 0 ) { modState |= 8; }
+
+ // Notify app of keypress
+ handleKeypressInGo(key, modState);
+}
+
+
+LPWSTR cstrToLPWSTR(const char *cstr) {
+ int wchars_num = MultiByteToWideChar( CP_UTF8 , 0 , cstr , -1, NULL , 0 );
+ wchar_t* wstr = new wchar_t[wchars_num+1];
+ MultiByteToWideChar( CP_UTF8 , 0 , cstr , -1, wstr , wchars_num );
+ return wstr;
+}
+
+// Credit: https://stackoverflow.com/a/9842450
+char* LPWSTRToCstr(LPWSTR input) {
+ int length = WideCharToMultiByte(CP_UTF8, 0, input, -1, 0, 0, NULL, NULL);
+ char* output = new char[length];
+ WideCharToMultiByte(CP_UTF8, 0, input, -1, output , length, NULL, NULL);
+ return output;
+}
+
+
+// Credit: https://building.enlyze.com/posts/writing-win32-apps-like-its-2020-part-3/
+typedef int (__cdecl *PGetDpiForMonitor)(HMONITOR, MONITOR_DPI_TYPE,UINT*,UINT*);
+void getDPIForWindow(struct Application *app)
+{
+ HMODULE hShcore = LoadLibraryW(L"shcore");
+ if (hShcore)
+ {
+ PGetDpiForMonitor pGetDpiForMonitor = reinterpret_cast(GetProcAddress(hShcore, "GetDpiForMonitor"));
+ if (pGetDpiForMonitor)
+ {
+ HMONITOR hMonitor = MonitorFromWindow(app->window, MONITOR_DEFAULTTOPRIMARY);
+ pGetDpiForMonitor(hMonitor, (MONITOR_DPI_TYPE)0, &app->dpix, &app->dpiy);
+ }
+ } else {
+ // We couldn't get the window's DPI above, so get the DPI of the primary monitor
+ // using an API that is available in all Windows versions.
+ HDC hScreenDC = GetDC(0);
+ app->dpix = GetDeviceCaps(hScreenDC, LOGPIXELSX);
+ app->dpiy = GetDeviceCaps(hScreenDC, LOGPIXELSY);
+ ReleaseDC(0, hScreenDC);
+ }
+}
+
+struct Application *NewApplication(const char *title, int width, int height, int resizable, int devtools, int fullscreen, int startHidden, int logLevel, int hideWindowOnClose) {
+
+ // Create application
+ struct Application *result = (struct Application*)malloc(sizeof(struct Application));
+
+ result->window = nullptr;
+ result->webview = nullptr;
+ result->webviewController = nullptr;
+
+ result->title = title;
+ result->width = width;
+ result->height = height;
+ result->resizable = resizable;
+ result->devtools = devtools;
+ result->fullscreen = fullscreen;
+ result->startHidden = startHidden;
+ result->logLevel = logLevel;
+ result->hideWindowOnClose = hideWindowOnClose;
+ result->webviewIsTranparent = false;
+ result->WindowIsTranslucent = false;
+ result->disableWindowIcon = false;
+
+ // Min/Max Width/Height
+ result->minWidth = 0;
+ result->minHeight = 0;
+ result->maxWidth = 0;
+ result->maxHeight = 0;
+
+ // Default colour
+ result->backgroundColour.R = 255;
+ result->backgroundColour.G = 255;
+ result->backgroundColour.B = 255;
+ result->backgroundColour.A = 255;
+
+ // Have a frame by default
+ result->frame = 1;
+
+ // Capture Main Thread
+ mainThread = GetCurrentThreadId();
+
+ // Startup url
+ result->startupURL = nullptr;
+
+ // Used to remember the window location when going fullscreen
+ result->previousPlacement = { sizeof(result->previousPlacement) };
+
+ // DPI
+ result->dpix = result->dpiy = 0;
+
+ return result;
+}
+
+void* GetWindowHandle(struct Application *app) {
+ return (void*)app->window;
+}
+
+void SetMinWindowSize(struct Application* app, int minWidth, int minHeight) {
+ app->minWidth = (LONG)minWidth;
+ app->minHeight = (LONG)minHeight;
+}
+
+void SetMaxWindowSize(struct Application* app, int maxWidth, int maxHeight) {
+ app->maxWidth = (LONG)maxWidth;
+ app->maxHeight = (LONG)maxHeight;
+}
+
+void SetBindings(struct Application *app, const char *bindings) {
+ std::string temp = std::string("window.wailsbindings = \"") + std::string(bindings) + std::string("\";");
+ app->bindings = new char[temp.length()+1];
+ memcpy(app->bindings, temp.c_str(), temp.length()+1);
+}
+
+void performShutdown(struct Application *app) {
+ if( app->startupURL != nullptr ) {
+ delete[] app->startupURL;
+ }
+ messageFromWindowCallback("WC");
+}
+
+// Credit: https://gist.github.com/ysc3839/b08d2bff1c7dacde529bed1d37e85ccf
+void enableTranslucentBackground(struct Application *app) {
+ HMODULE hUser = GetModuleHandleA("user32.dll");
+ if (hUser)
+ {
+ pfnSetWindowCompositionAttribute setWindowCompositionAttribute = (pfnSetWindowCompositionAttribute)GetProcAddress(hUser, "SetWindowCompositionAttribute");
+ if (setWindowCompositionAttribute)
+ {
+ ACCENT_POLICY accent = { ACCENT_ENABLE_BLURBEHIND, 0, 0, 0 };
+ WINDOWCOMPOSITIONATTRIBDATA data;
+ data.Attrib = WCA_ACCENT_POLICY;
+ data.pvData = &accent;
+ data.cbData = sizeof(accent);
+ setWindowCompositionAttribute(app->window, &data);
+ }
+ }
+}
+
+LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
+
+ struct Application *app = (struct Application *)GetWindowLongPtr(hwnd, GWLP_USERDATA);
+
+ switch(msg) {
+
+ case WM_CREATE: {
+ createApplicationMenu(hwnd);
+ break;
+ }
+ case WM_COMMAND:
+ menuClicked(LOWORD(wParam));
+ break;
+
+ case WM_CLOSE: {
+ DestroyWindow( app->window );
+ break;
+ }
+ case WM_DESTROY: {
+ if( app->hideWindowOnClose ) {
+ Hide(app);
+ } else {
+ PostQuitMessage(0);
+ }
+ break;
+ }
+ case WM_SIZE: {
+ if ( app == NULL ) {
+ return 0;
+ }
+ if( app->webviewController != nullptr) {
+ RECT bounds;
+ GetClientRect(app->window, &bounds);
+ app->webviewController->put_Bounds(bounds);
+ }
+ break;
+ }
+ case WM_KEYDOWN:
+ // This is needed because webview2 is sometimes not in focus
+ // https://github.com/MicrosoftEdge/WebView2Feedback/issues/1541
+ processKeyPress(wParam);
+ break;
+ case WM_GETMINMAXINFO: {
+ // Exit early if this is called before the window is created.
+ if ( app == NULL ) {
+ return 0;
+ }
+
+ // update DPI
+ getDPIForWindow(app);
+ double DPIScaleX = app->dpix/96.0;
+ double DPIScaleY = app->dpiy/96.0;
+
+ RECT rcWind;
+ POINT ptDiff;
+ GetWindowRect(hwnd, &rcWind);
+
+ int widthExtra = (rcWind.right - rcWind.left);
+ int heightExtra = (rcWind.bottom - rcWind.top);
+
+ LPMINMAXINFO mmi = (LPMINMAXINFO) lParam;
+ if (app->minWidth > 0 && app->minHeight > 0) {
+ mmi->ptMinTrackSize.x = app->minWidth * DPIScaleX;
+ mmi->ptMinTrackSize.y = app->minHeight * DPIScaleY;
+ }
+ if (app->maxWidth > 0 && app->maxHeight > 0) {
+ mmi->ptMaxSize.x = app->maxWidth * DPIScaleX;
+ mmi->ptMaxSize.y = app->maxHeight * DPIScaleY;
+ mmi->ptMaxTrackSize.x = app->maxWidth * DPIScaleX;
+ mmi->ptMaxTrackSize.y = app->maxHeight * DPIScaleY;
+ }
+ return 0;
+ }
+ default:
+ return DefWindowProc(hwnd, msg, wParam, lParam);
+ }
+ return 0;
+}
+
+void init(struct Application *app, const char* js) {
+ LPCWSTR wjs = cstrToLPWSTR(js);
+ app->webview->AddScriptToExecuteOnDocumentCreated(wjs, nullptr);
+ delete[] wjs;
+}
+
+void execJS(struct Application* app, const char *script) {
+ LPWSTR s = cstrToLPWSTR(script);
+ app->webview->ExecuteScript(s, nullptr);
+ delete[] s;
+}
+
+void loadAssets(struct Application* app) {
+
+ // setup window.wailsInvoke
+ std::string initialCode = std::string("window.wailsInvoke=function(m){window.chrome.webview.postMessage(m)};");
+
+ // Load bindings
+ initialCode += std::string(app->bindings);
+ delete[] app->bindings;
+
+ // Load runtime
+ initialCode += std::string((const char*)&runtime);
+
+ int index = 1;
+ while(1) {
+ // Get next asset pointer
+ const unsigned char *asset = assets[index];
+
+ // If we have no more assets, break
+ if (asset == 0x00) {
+ break;
+ }
+
+ initialCode += std::string((const char*)asset);
+ index++;
+ };
+
+ // Disable context menu if not in debug mode
+ if( debug != 1 ) {
+ initialCode += std::string("wails._.DisableDefaultContextMenu();");
+ }
+
+ initialCode += std::string("window.wailsInvoke('completed');");
+
+ // Keep a copy of the code
+ app->initialCode = new char[initialCode.length()+1];
+ memcpy(app->initialCode, initialCode.c_str(), initialCode.length()+1);
+
+ execJS(app, app->initialCode);
+
+ // Show app if we need to
+ if( app->startHidden == false ) {
+ Show(app);
+ }
+}
+
+// This is called when all our assets are loaded into the DOM
+void completed(struct Application* app) {
+ delete[] app->initialCode;
+ app->initialCode = nullptr;
+
+ // Process whether window should show by default
+ int startVisibility = SW_SHOWNORMAL;
+ if ( app->startHidden == 1 ) {
+ startVisibility = SW_HIDE;
+ }
+
+ // Fix for webview2 bug: https://github.com/MicrosoftEdge/WebView2Feedback/issues/1077
+ // Will be fixed in next stable release
+ app->webviewController->put_IsVisible(false);
+ app->webviewController->put_IsVisible(true);
+
+ // Private setTitle as we're on the main thread
+ if( app->frame == 1) {
+ setTitle(app, app->title);
+ }
+
+ ShowWindow(app->window, startVisibility);
+ UpdateWindow(app->window);
+ SetFocus(app->window);
+
+ if( app->startupURL == nullptr ) {
+ messageFromWindowCallback("SS");
+ return;
+ }
+ std::string readyMessage = std::string("SS") + std::string(app->startupURL);
+ messageFromWindowCallback(readyMessage.c_str());
+}
+
+//
+bool initWebView2(struct Application *app, int debugEnabled, messageCallback cb) {
+
+ debug = debugEnabled;
+
+ CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);
+
+ std::atomic_flag flag = ATOMIC_FLAG_INIT;
+ flag.test_and_set();
+
+ char currentExePath[MAX_PATH];
+ GetModuleFileNameA(NULL, currentExePath, MAX_PATH);
+ char *currentExeName = PathFindFileNameA(currentExePath);
+
+ std::wstring_convert> wideCharConverter;
+ std::wstring userDataFolder =
+ wideCharConverter.from_bytes(std::getenv("APPDATA"));
+ std::wstring currentExeNameW = wideCharConverter.from_bytes(currentExeName);
+
+ ICoreWebView2Controller *controller;
+ ICoreWebView2* webview;
+
+ HRESULT res = CreateCoreWebView2EnvironmentWithOptions(
+ nullptr, (userDataFolder + L"/" + currentExeNameW).c_str(), nullptr,
+ new wv2ComHandler(app, app->window, cb,
+ [&](ICoreWebView2Controller *webviewController) {
+ controller = webviewController;
+ controller->get_CoreWebView2(&webview);
+ webview->AddRef();
+ ICoreWebView2Settings* settings;
+ webview->get_Settings(&settings);
+ if ( debugEnabled == 0 ) {
+ settings->put_AreDefaultContextMenusEnabled(FALSE);
+ }
+ // Fix for invisible webview
+ if( app->startHidden ) {}
+ controller->MoveFocus(COREWEBVIEW2_MOVE_FOCUS_REASON_PROGRAMMATIC);
+ flag.clear();
+ }));
+ if (!SUCCEEDED(res))
+ {
+ switch (res)
+ {
+ case HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND):
+ {
+ MessageBox(
+ app->window,
+ L"Couldn't find Edge installation. "
+ "Do you have a version installed that's compatible with this "
+ "WebView2 SDK version?",
+ nullptr, MB_OK);
+ }
+ break;
+ case HRESULT_FROM_WIN32(ERROR_FILE_EXISTS):
+ {
+ MessageBox(
+ app->window, L"User data folder cannot be created because a file with the same name already exists.", nullptr, MB_OK);
+ }
+ break;
+ case E_ACCESSDENIED:
+ {
+ MessageBox(
+ app->window, L"Unable to create user data folder, Access Denied.", nullptr, MB_OK);
+ }
+ break;
+ case E_FAIL:
+ {
+ MessageBox(
+ app->window, L"Edge runtime unable to start", nullptr, MB_OK);
+ }
+ break;
+ default:
+ {
+ MessageBox(app->window, L"Failed to create WebView2 environment", nullptr, MB_OK);
+ }
+ }
+ }
+
+ if (res != S_OK) {
+ CoUninitialize();
+ return false;
+ }
+
+ MSG msg = {};
+ while (flag.test_and_set() && GetMessage(&msg, NULL, 0, 0)) {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+ app->webviewController = controller;
+ app->webview = webview;
+
+ // Resize WebView to fit the bounds of the parent window
+ RECT bounds;
+ GetClientRect(app->window, &bounds);
+ app->webviewController->put_Bounds(bounds);
+
+ // Let the backend know we have initialised
+ app->webview->AddScriptToExecuteOnDocumentCreated(L"window.chrome.webview.postMessage('initialised');", nullptr);
+ // Load the HTML
+ LPCWSTR html = (LPCWSTR) cstrToLPWSTR((char*)assets[0]);
+ app->webview->Navigate(html);
+
+ if( app->webviewIsTranparent ) {
+ wchar_t szBuff[64];
+ ICoreWebView2Controller2 *wc2;
+ wc2 = nullptr;
+ app->webviewController->QueryInterface(IID_ICoreWebView2Controller2, (void**)&wc2);
+
+ COREWEBVIEW2_COLOR wvColor;
+ wvColor.R = app->backgroundColour.R;
+ wvColor.G = app->backgroundColour.G;
+ wvColor.B = app->backgroundColour.B;
+ wvColor.A = app->backgroundColour.A == 0 ? 0 : 255;
+ if( app->WindowIsTranslucent ) {
+ wvColor.A = 0;
+ }
+ HRESULT result = wc2->put_DefaultBackgroundColor(wvColor);
+ if (!SUCCEEDED(result))
+ {
+ switch (result)
+ {
+ case HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND):
+ {
+ MessageBox(
+ app->window,
+ L"Couldn't find Edge installation. "
+ "Do you have a version installed that's compatible with this "
+ "WebView2 SDK version?",
+ nullptr, MB_OK);
+ }
+ break;
+ case HRESULT_FROM_WIN32(ERROR_FILE_EXISTS):
+ {
+ MessageBox(
+ app->window, L"User data folder cannot be created because a file with the same name already exists.", nullptr, MB_OK);
+ }
+ break;
+ case E_ACCESSDENIED:
+ {
+ MessageBox(
+ app->window, L"Unable to create user data folder, Access Denied.", nullptr, MB_OK);
+ }
+ break;
+ case E_FAIL:
+ {
+ MessageBox(
+ app->window, L"Edge runtime unable to start", nullptr, MB_OK);
+ }
+ break;
+ default:
+ {
+ MessageBox(app->window, L"Failed to create WebView2 environment", nullptr, MB_OK);
+ }
+ }
+ }
+
+ }
+
+ messageFromWindowCallback("Ej{\"name\":\"wails:launched\",\"data\":[]}");
+
+ return true;
+}
+
+void initialCallback(std::string message) {
+ printf("MESSAGE=%s\n", message);
+}
+
+void Run(struct Application* app, int argc, char **argv) {
+
+ // Register the window class.
+ const wchar_t CLASS_NAME[] = L"Ffenestri";
+
+ WNDCLASSEX wc = { };
+
+ wc.cbSize = sizeof(WNDCLASSEX);
+ wc.lpfnWndProc = WndProc;
+ wc.hInstance = GetModuleHandle(NULL);
+ wc.lpszClassName = CLASS_NAME;
+
+ if( app->disableWindowIcon == false ) {
+ wc.hIcon = LoadIcon(wc.hInstance, MAKEINTRESOURCE(100));
+ wc.hIconSm = LoadIcon(wc.hInstance, MAKEINTRESOURCE(100));
+ }
+
+ // Configure translucency
+ DWORD dwExStyle = 0;
+ if ( app->WindowIsTranslucent) {
+ dwExStyle = WS_EX_NOREDIRECTIONBITMAP;
+ wc.hbrBackground = CreateSolidBrush(RGB(255,255,255));
+ }
+
+ RegisterClassEx(&wc);
+
+ // Process window style
+ DWORD windowStyle = WS_OVERLAPPEDWINDOW | WS_THICKFRAME | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX;
+
+ if (app->resizable == 0) {
+ windowStyle &= ~WS_MAXIMIZEBOX;
+ windowStyle &= ~WS_THICKFRAME;
+ }
+ if ( app->frame == 0 ) {
+ windowStyle &= ~WS_OVERLAPPEDWINDOW;
+ windowStyle &= ~WS_CAPTION;
+ windowStyle |= WS_POPUP;
+ }
+
+ // Create the window.
+ app->window = CreateWindowEx(
+ dwExStyle, // Optional window styles.
+ CLASS_NAME, // Window class
+ L"", // Window text
+ windowStyle, // Window style
+
+ // Size and position
+ CW_USEDEFAULT, CW_USEDEFAULT, app->width, app->height,
+
+ NULL, // Parent window
+ NULL, // Menu
+ wc.hInstance, // Instance handle
+ NULL // Additional application data
+ );
+
+ if (app->window == NULL)
+ {
+ return;
+ }
+
+ if ( app->fullscreen ) {
+ fullscreen(app);
+ }
+
+ // Credit: https://stackoverflow.com/a/35482689
+ if( app->disableWindowIcon && app->frame == 1 ) {
+ int extendedStyle = GetWindowLong(app->window, GWL_EXSTYLE);
+ SetWindowLong(app->window, GWL_EXSTYLE, extendedStyle | WS_EX_DLGMODALFRAME);
+ SetWindowPos(nullptr, nullptr, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER);
+ }
+
+ if ( app->WindowIsTranslucent ) {
+
+ // Enable the translucent background effect
+ enableTranslucentBackground(app);
+
+ // Setup transparency of main window. This allows the blur to show through.
+ SetLayeredWindowAttributes(app->window,RGB(255,255,255),0,LWA_COLORKEY);
+ }
+
+ // Store application pointer in window handle
+ SetWindowLongPtr(app->window, GWLP_USERDATA, (LONG_PTR)app);
+
+ // private center() as we are on main thread
+ center(app);
+
+ // Add webview2
+ initWebView2(app, debug, initialCallback);
+
+
+ // Main event loop
+ MSG msg;
+ BOOL res;
+ while ((res = GetMessage(&msg, NULL, 0, 0)) != -1) {
+ if (msg.hwnd) {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ continue;
+ }
+ if (msg.message == WM_APP) {
+ dispatchFunction *f = (dispatchFunction*) msg.lParam;
+ (*f)();
+ delete(f);
+ } else if (msg.message == WM_QUIT) {
+ performShutdown(app);
+ return;
+ }
+ }
+}
+
+void SetDebug(struct Application* app, int flag) {
+ debug = flag;
+}
+
+void ExecJS(struct Application* app, const char *script) {
+ ON_MAIN_THREAD(
+ execJS(app, script);
+ );
+}
+
+void hide(struct Application* app) {
+ ShowWindow(app->window, SW_HIDE);
+}
+
+void Hide(struct Application* app) {
+ ON_MAIN_THREAD(
+ hide(app);
+ );
+}
+
+void show(struct Application* app) {
+ ShowWindow(app->window, SW_SHOW);
+}
+
+void Show(struct Application* app) {
+ ON_MAIN_THREAD(
+ show(app);
+ );
+}
+
+void DisableWindowIcon(struct Application* app) {
+ app->disableWindowIcon = true;
+}
+
+void center(struct Application* app) {
+
+ HMONITOR currentMonitor = MonitorFromWindow(app->window, MONITOR_DEFAULTTONEAREST);
+ MONITORINFO info = {0};
+ info.cbSize = sizeof(info);
+ GetMonitorInfoA(currentMonitor, &info);
+ RECT workRect = info.rcWork;
+ LONG screenMiddleW = (workRect.right - workRect.left) / 2;
+ LONG screenMiddleH = (workRect.bottom - workRect.top) / 2;
+ RECT winRect;
+ if (app->frame == 1) {
+ GetWindowRect(app->window, &winRect);
+ } else {
+ GetClientRect(app->window, &winRect);
+ }
+ LONG winWidth = winRect.right - winRect.left;
+ LONG winHeight = winRect.bottom - winRect.top;
+
+ LONG windowX = screenMiddleW - (winWidth / 2);
+ LONG windowY = screenMiddleH - (winHeight / 2);
+
+ SetWindowPos(app->window, HWND_TOP, windowX, windowY, winWidth, winHeight, SWP_NOSIZE);
+}
+
+void Center(struct Application* app) {
+ ON_MAIN_THREAD(
+ center(app);
+ );
+}
+
+UINT getWindowPlacement(struct Application* app) {
+ WINDOWPLACEMENT lpwndpl;
+ lpwndpl.length = sizeof(WINDOWPLACEMENT);
+ BOOL result = GetWindowPlacement(app->window, &lpwndpl);
+ if( result == 0 ) {
+ // TODO: Work out what this call failing means
+ return -1;
+ }
+ return lpwndpl.showCmd;
+}
+
+int isMaximised(struct Application* app) {
+ return getWindowPlacement(app) == SW_SHOWMAXIMIZED;
+}
+
+void maximise(struct Application* app) {
+ ShowWindow(app->window, SW_MAXIMIZE);
+}
+
+void Maximise(struct Application* app) {
+ ON_MAIN_THREAD(
+ maximise(app);
+ );
+}
+
+void unmaximise(struct Application* app) {
+ ShowWindow(app->window, SW_RESTORE);
+}
+
+void Unmaximise(struct Application* app) {
+ ON_MAIN_THREAD(
+ unmaximise(app);
+ );
+}
+
+
+void ToggleMaximise(struct Application* app) {
+ if(isMaximised(app)) {
+ return Unmaximise(app);
+ }
+ return Maximise(app);
+}
+
+int isMinimised(struct Application* app) {
+ return getWindowPlacement(app) == SW_SHOWMINIMIZED;
+}
+
+void minimise(struct Application* app) {
+ ShowWindow(app->window, SW_MINIMIZE);
+}
+
+void Minimise(struct Application* app) {
+ ON_MAIN_THREAD(
+ minimise(app);
+ );
+}
+
+void unminimise(struct Application* app) {
+ ShowWindow(app->window, SW_RESTORE);
+}
+
+void Unminimise(struct Application* app) {
+ ON_MAIN_THREAD(
+ unminimise(app);
+ );
+}
+
+void ToggleMinimise(struct Application* app) {
+ if(isMinimised(app)) {
+ return Unminimise(app);
+ }
+ return Minimise(app);
+}
+
+void SetColour(struct Application* app, int red, int green, int blue, int alpha) {
+ app->backgroundColour.R = red;
+ app->backgroundColour.G = green;
+ app->backgroundColour.B = blue;
+ app->backgroundColour.A = alpha;
+}
+
+void SetSize(struct Application* app, int width, int height) {
+ if( app->maxWidth > 0 && width > app->maxWidth ) {
+ width = app->maxWidth;
+ }
+ if ( app->maxHeight > 0 && height > app->maxHeight ) {
+ height = app->maxHeight;
+ }
+ SetWindowPos(app->window, nullptr, 0, 0, width, height, SWP_NOMOVE);
+}
+
+void setPosition(struct Application* app, int x, int y) {
+ HMONITOR currentMonitor = MonitorFromWindow(app->window, MONITOR_DEFAULTTONEAREST);
+ MONITORINFO info = {0};
+ info.cbSize = sizeof(info);
+ GetMonitorInfoA(currentMonitor, &info);
+ RECT workRect = info.rcWork;
+ LONG newX = workRect.left + x;
+ LONG newY = workRect.top + y;
+
+ SetWindowPos(app->window, HWND_TOP, newX, newY, 0, 0, SWP_NOSIZE);
+}
+
+void SetPosition(struct Application* app, int x, int y) {
+ ON_MAIN_THREAD(
+ setPosition(app, x, y);
+ );
+}
+
+void Quit(struct Application* app) {
+ // Override the hide window on close flag
+ app->hideWindowOnClose = 0;
+ ON_MAIN_THREAD(
+ DestroyWindow(app->window);
+ );
+}
+
+
+// Credit: https://stackoverflow.com/a/6693107
+void setTitle(struct Application* app, const char *title) {
+ LPCTSTR text = cstrToLPWSTR(title);
+ SetWindowText(app->window, text);
+ delete[] text;
+}
+
+void SetTitle(struct Application* app, const char *title) {
+ ON_MAIN_THREAD(
+ setTitle(app, title);
+ );
+}
+
+void fullscreen(struct Application* app) {
+
+ // Ensure we aren't in fullscreen
+ if (app->isFullscreen) return;
+
+ app->isFullscreen = true;
+ app->previousWindowStyle = GetWindowLong(app->window, GWL_STYLE);
+ MONITORINFO mi = { sizeof(mi) };
+ if (GetWindowPlacement(app->window, &(app->previousPlacement)) && GetMonitorInfo(MonitorFromWindow(app->window, MONITOR_DEFAULTTOPRIMARY), &mi)) {
+ SetWindowLong(app->window, GWL_STYLE, app->previousWindowStyle & ~WS_OVERLAPPEDWINDOW);
+ SetWindowPos(app->window, HWND_TOP,
+ mi.rcMonitor.left,
+ mi.rcMonitor.top,
+ mi.rcMonitor.right - mi.rcMonitor.left,
+ mi.rcMonitor.bottom - mi.rcMonitor.top,
+ SWP_NOOWNERZORDER | SWP_FRAMECHANGED);
+ }
+}
+
+void Fullscreen(struct Application* app) {
+ ON_MAIN_THREAD(
+ fullscreen(app);
+ show(app);
+ );
+}
+
+void unfullscreen(struct Application* app) {
+ if (app->isFullscreen) {
+ SetWindowLong(app->window, GWL_STYLE, app->previousWindowStyle);
+ SetWindowPlacement(app->window, &(app->previousPlacement));
+ SetWindowPos(app->window, NULL, 0, 0, 0, 0,
+ SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER |
+ SWP_NOOWNERZORDER | SWP_FRAMECHANGED);
+ app->isFullscreen = false;
+ }
+}
+
+void UnFullscreen(struct Application* app) {
+ ON_MAIN_THREAD(
+ unfullscreen(app);
+ );
+}
+
+void DisableFrame(struct Application* app) {
+ app->frame = 0;
+}
+
+// WebviewIsTransparent will make the webview transparent
+// revealing the window underneath
+void WebviewIsTransparent(struct Application *app) {
+ app->webviewIsTranparent = true;
+}
+
+void WindowIsTranslucent(struct Application *app) {
+ app->WindowIsTranslucent = true;
+}
+
+
+void OpenDialog(struct Application* app, char *callbackID, char *title, char *filters, char *defaultFilename, char *defaultDir, int allowFiles, int allowDirs, int allowMultiple, int showHiddenFiles, int canCreateDirectories, int resolvesAliases, int treatPackagesAsDirectories) {
+}
+void SaveDialog(struct Application* app, char *callbackID, char *title, char *filters, char *defaultFilename, char *defaultDir, int showHiddenFiles, int canCreateDirectories, int treatPackagesAsDirectories) {
+}
+void MessageDialog(struct Application* app, char *callbackID, char *type, char *title, char *message, char *icon, char *button1, char *button2, char *button3, char *button4, char *defaultButton, char *cancelButton) {
+}
+void DarkModeEnabled(struct Application* app, char *callbackID) {
+}
+void SetApplicationMenu(struct Application* app, const char *applicationMenuJSON) {
+}
+void AddTrayMenu(struct Application* app, const char *menuTrayJSON) {
+}
+void SetTrayMenu(struct Application* app, const char *menuTrayJSON) {
+}
+void DeleteTrayMenuByID(struct Application* app, const char *id) {
+}
+void UpdateTrayMenuLabel(struct Application* app, const char* JSON) {
+}
+void AddContextMenu(struct Application* app, char *contextMenuJSON) {
+}
+void UpdateContextMenu(struct Application* app, char *contextMenuJSON) {
+}
\ No newline at end of file
diff --git a/v2/internal/ffenestri/ffenestri_windows.go b/v2/internal/ffenestri/ffenestri_windows.go
new file mode 100644
index 000000000..ce5d821f3
--- /dev/null
+++ b/v2/internal/ffenestri/ffenestri_windows.go
@@ -0,0 +1,198 @@
+package ffenestri
+
+import "C"
+
+/*
+
+#cgo windows CXXFLAGS: -std=c++11
+#cgo windows,amd64 LDFLAGS: -lgdi32 -lole32 -lShlwapi -luser32 -loleaut32 -ldwmapi
+
+#include "ffenestri.h"
+
+extern void DisableWindowIcon(struct Application* app);
+
+*/
+import "C"
+import (
+ "github.com/ztrue/tracerr"
+ "os"
+
+ "github.com/wailsapp/wails/v2/pkg/menu"
+)
+
+// Setup the global caches
+var globalCheckboxCache = NewCheckboxCache()
+var globalRadioGroupCache = NewRadioGroupCache()
+var globalRadioGroupMap = NewRadioGroupMap()
+var globalApplicationMenu *Menu
+
+type menuType string
+
+const (
+ appMenuType menuType = "ApplicationMenu"
+ contextMenuType
+ trayMenuType
+)
+
+func (a *Application) processPlatformSettings() error {
+
+ menuManager = a.menuManager
+ config := a.config.Windows
+ if config == nil {
+ return nil
+ }
+
+ // Check if the webview should be transparent
+ if config.WebviewIsTransparent {
+ C.WebviewIsTransparent(a.app)
+ }
+
+ if config.WindowIsTranslucent {
+ C.WindowIsTranslucent(a.app)
+ }
+
+ if config.DisableWindowIcon {
+ C.DisableWindowIcon(a.app)
+ }
+
+ // Unfortunately, we need to store this in the package variable so the C callback can see it
+ applicationMenu = a.menuManager.GetProcessedApplicationMenu()
+
+ //
+ //// Process tray
+ //trays, err := a.menuManager.GetTrayMenus()
+ //if err != nil {
+ // return err
+ //}
+ //if trays != nil {
+ // for _, tray := range trays {
+ // C.AddTrayMenu(a.app, a.string2CString(tray))
+ // }
+ //}
+ //
+ //// Process context menus
+ //contextMenus, err := a.menuManager.GetContextMenus()
+ //if err != nil {
+ // return err
+ //}
+ //if contextMenus != nil {
+ // for _, contextMenu := range contextMenus {
+ // C.AddContextMenu(a.app, a.string2CString(contextMenu))
+ // }
+ //}
+ //
+ //// Process URL Handlers
+ //if a.config.Mac.URLHandlers != nil {
+ // C.HasURLHandlers(a.app)
+ //}
+
+ return nil
+}
+
+func (c *Client) updateApplicationMenu() {
+ applicationMenu = c.app.menuManager.GetProcessedApplicationMenu()
+ createApplicationMenu(uintptr(C.GetWindowHandle(c.app.app)))
+}
+
+/* ---------------------------------------------------------------------------------
+
+Application Menu
+----------------
+There's only 1 application menu and this is where we create it. This method
+is called from C after the window is created and the WM_CREATE message has
+been sent.
+
+*/
+
+func checkFatal(err error) {
+ if err != nil {
+ tracerr.PrintSourceColor(err)
+ globalRadioGroupCache.Dump()
+ globalRadioGroupMap.Dump()
+ os.Exit(1)
+ }
+}
+
+//export createApplicationMenu
+func createApplicationMenu(hwnd uintptr) {
+
+ if applicationMenu == nil {
+ return
+ }
+
+ var err error
+ window := win32Window(hwnd)
+
+ if globalApplicationMenu != nil {
+ checkFatal(globalApplicationMenu.Destroy())
+ }
+
+ globalApplicationMenu, err = createMenu(applicationMenu, appMenuType)
+ checkFatal(err)
+
+ err = setWindowMenu(window, globalApplicationMenu.menu)
+ checkFatal(err)
+}
+
+//export handleKeypressInGo
+func handleKeypressInGo(keycode uint16, modifiers uint8) {
+ //fmt.Printf("Key code: %#x\n", keycode)
+ menuID, menuType := getCallbackForKeyPress(keycode, modifiers)
+ if menuID == "" {
+ return
+ }
+ err := menuManager.ProcessClick(menuID, "", string(menuType), "")
+ if err != nil {
+ println(err.Error())
+ }
+}
+
+/*
+This method is called by C when a menu item is pressed
+*/
+
+//export menuClicked
+func menuClicked(id uint32) {
+ win32MenuID := win32MenuItemID(id)
+ //println("Got click from menu id", win32MenuID)
+
+ // Get the menu from the cache
+ menuItemDetails := getMenuCacheEntry(win32MenuID)
+ wailsMenuID := wailsMenuItemID(menuItemDetails.item.ID)
+
+ //println("Got click from menu id", win32MenuID, "- wails menu ID", wailsMenuID)
+ //spew.Dump(menuItemDetails)
+
+ switch menuItemDetails.item.Type {
+ case menu.CheckboxType:
+
+ // Determine if the menu is set or not
+ res, _, err := win32GetMenuState.Call(uintptr(menuItemDetails.parent), uintptr(id), uintptr(MF_BYCOMMAND))
+ if int(res) == -1 {
+ checkFatal(err)
+ }
+
+ flag := MF_CHECKED
+ if uint32(res) == MF_CHECKED {
+ flag = MF_UNCHECKED
+ }
+
+ for _, menuid := range globalCheckboxCache.win32MenuIDsForWailsMenuID(wailsMenuID) {
+ //println("setting menuid", menuid, "with flag", flag)
+ menuItemDetails := getMenuCacheEntry(menuid)
+ res, _, err = win32CheckMenuItem.Call(uintptr(menuItemDetails.parent), uintptr(menuid), uintptr(flag))
+ if int(res) == -1 {
+ checkFatal(err)
+ }
+ }
+ case menu.RadioType:
+ err := selectRadioItemFromWailsMenuID(wailsMenuID, win32MenuID)
+ checkFatal(err)
+ }
+
+ // Print the click error - it's not fatal
+ err := menuManager.ProcessClick(menuItemDetails.item.ID, "", string(menuItemDetails.menuType), "")
+ if err != nil {
+ println(err.Error())
+ }
+}
diff --git a/v2/internal/ffenestri/ffenestri_windows.h b/v2/internal/ffenestri/ffenestri_windows.h
new file mode 100644
index 000000000..1e39bea10
--- /dev/null
+++ b/v2/internal/ffenestri/ffenestri_windows.h
@@ -0,0 +1,95 @@
+
+#ifndef _FFENESTRI_WINDOWS_H
+#define _FFENESTRI_WINDOWS_H
+
+#define WIN32_LEAN_AND_MEAN
+#define UNICODE 1
+
+#include "ffenestri.h"
+#include
+#include
+#include
+#include
+#include "windows/WebView2.h"
+
+#include "assets.h"
+
+// TODO:
+//#include "userdialogicons.h"
+
+
+struct Application{
+ // Window specific
+ HWND window;
+ ICoreWebView2 *webview;
+ ICoreWebView2Controller* webviewController;
+
+ // Application
+ const char *title;
+ int width;
+ int height;
+ int resizable;
+ int devtools;
+ int fullscreen;
+ int startHidden;
+ int logLevel;
+ int hideWindowOnClose;
+ int minSizeSet;
+ LONG minWidth;
+ LONG minHeight;
+ int maxSizeSet;
+ LONG maxWidth;
+ LONG maxHeight;
+ int frame;
+ char *startupURL;
+ bool webviewIsTranparent;
+ bool WindowIsTranslucent;
+ COREWEBVIEW2_COLOR backgroundColour;
+ bool disableWindowIcon;
+
+ // Used by fullscreen/unfullscreen
+ bool isFullscreen;
+ WINDOWPLACEMENT previousPlacement;
+ DWORD previousWindowStyle;
+
+ // placeholders
+ char* bindings;
+ char* initialCode;
+
+ // DPI
+ UINT dpix;
+ UINT dpiy;
+};
+
+#define ON_MAIN_THREAD(code) dispatch( [=]{ code; } )
+
+typedef std::function dispatchFunction;
+typedef std::function messageCallback;
+typedef std::function comHandlerCallback;
+
+void center(struct Application*);
+void setTitle(struct Application* app, const char *title);
+void fullscreen(struct Application* app);
+void unfullscreen(struct Application* app);
+char* LPWSTRToCstr(LPWSTR input);
+
+// called when the DOM is ready
+void loadAssets(struct Application* app);
+
+// called when the application assets have been loaded into the DOM
+void completed(struct Application* app);
+
+// Processes the given keycode
+void processKeyPress(UINT key);
+
+// Callback
+extern "C" {
+ void DisableWindowIcon(struct Application* app);
+ void messageFromWindowCallback(const char *);
+ void* GetWindowHandle(struct Application*);
+ void createApplicationMenu(HWND hwnd);
+ void menuClicked(UINT id);
+ void handleKeypressInGo(UINT, BYTE);
+}
+
+#endif
\ No newline at end of file
diff --git a/v2/internal/ffenestri/hashmap.h b/v2/internal/ffenestri/hashmap.h
new file mode 100644
index 000000000..0278bc3d6
--- /dev/null
+++ b/v2/internal/ffenestri/hashmap.h
@@ -0,0 +1,518 @@
+/*
+ The latest version of this library is available on GitHub;
+ https://github.com/sheredom/hashmap.h
+*/
+
+/*
+ This is free and unencumbered software released into the public domain.
+
+ Anyone is free to copy, modify, publish, use, compile, sell, or
+ distribute this software, either in source code form or as a compiled
+ binary, for any purpose, commercial or non-commercial, and by any
+ means.
+
+ In jurisdictions that recognize copyright laws, the author or authors
+ of this software dedicate any and all copyright interest in the
+ software to the public domain. We make this dedication for the benefit
+ of the public at large and to the detriment of our heirs and
+ successors. We intend this dedication to be an overt act of
+ relinquishment in perpetuity of all present and future rights to this
+ software under copyright law.
+
+ 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 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.
+
+ For more information, please refer to
+*/
+#ifndef SHEREDOM_HASHMAP_H_INCLUDED
+#define SHEREDOM_HASHMAP_H_INCLUDED
+
+#if defined(_MSC_VER)
+// Workaround a bug in the MSVC runtime where it uses __cplusplus when not
+// defined.
+#pragma warning(push, 0)
+#pragma warning(disable : 4668)
+#endif
+#include
+#include
+
+#if (defined(_MSC_VER) && defined(__AVX__)) || \
+ (!defined(_MSC_VER) && defined(__SSE4_2__))
+#define HASHMAP_SSE42
+#endif
+
+#if defined(HASHMAP_SSE42)
+#include
+#endif
+
+#if defined(_MSC_VER)
+#pragma warning(pop)
+#endif
+
+#if defined(_MSC_VER)
+#pragma warning(push)
+// Stop MSVC complaining about not inlining functions.
+#pragma warning(disable : 4710)
+// Stop MSVC complaining about inlining functions!
+#pragma warning(disable : 4711)
+#elif defined(__clang__)
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wunused-function"
+#endif
+
+#if defined(_MSC_VER)
+#define HASHMAP_USED
+#elif defined(__GNUC__)
+#define HASHMAP_USED __attribute__((used))
+#else
+#define HASHMAP_USED
+#endif
+
+/* We need to keep keys and values. */
+struct hashmap_element_s {
+ const char *key;
+ unsigned key_len;
+ int in_use;
+ void *data;
+};
+
+/* A hashmap has some maximum size and current size, as well as the data to
+ * hold. */
+struct hashmap_s {
+ unsigned table_size;
+ unsigned size;
+ struct hashmap_element_s *data;
+};
+
+#define HASHMAP_MAX_CHAIN_LENGTH (8)
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+/// @brief Create a hashmap.
+/// @param initial_size The initial size of the hashmap. Must be a power of two.
+/// @param out_hashmap The storage for the created hashmap.
+/// @return On success 0 is returned.
+///
+/// Note that the initial size of the hashmap must be a power of two, and
+/// creation of the hashmap will fail if this is not the case.
+static int hashmap_create(const unsigned initial_size,
+ struct hashmap_s *const out_hashmap) HASHMAP_USED;
+
+/// @brief Put an element into the hashmap.
+/// @param hashmap The hashmap to insert into.
+/// @param key The string key to use.
+/// @param len The length of the string key.
+/// @param value The value to insert.
+/// @return On success 0 is returned.
+///
+/// The key string slice is not copied when creating the hashmap entry, and thus
+/// must remain a valid pointer until the hashmap entry is removed or the
+/// hashmap is destroyed.
+static int hashmap_put(struct hashmap_s *const hashmap, const char *const key,
+ const unsigned len, void *const value) HASHMAP_USED;
+
+/// @brief Get an element from the hashmap.
+/// @param hashmap The hashmap to get from.
+/// @param key The string key to use.
+/// @param len The length of the string key.
+/// @return The previously set element, or NULL if none exists.
+static void *hashmap_get(const struct hashmap_s *const hashmap,
+ const char *const key,
+ const unsigned len) HASHMAP_USED;
+
+/// @brief Remove an element from the hashmap.
+/// @param hashmap The hashmap to remove from.
+/// @param key The string key to use.
+/// @param len The length of the string key.
+/// @return On success 0 is returned.
+static int hashmap_remove(struct hashmap_s *const hashmap,
+ const char *const key,
+ const unsigned len) HASHMAP_USED;
+
+/// @brief Iterate over all the elements in a hashmap.
+/// @param hashmap The hashmap to iterate over.
+/// @param f The function pointer to call on each element.
+/// @param context The context to pass as the first argument to f.
+/// @return If the entire hashmap was iterated then 0 is returned. Otherwise if
+/// the callback function f returned non-zero then non-zero is returned.
+static int hashmap_iterate(const struct hashmap_s *const hashmap,
+ int (*f)(void *const context, void *const value),
+ void *const context) HASHMAP_USED;
+
+/// @brief Iterate over all the elements in a hashmap.
+/// @param hashmap The hashmap to iterate over.
+/// @param f The function pointer to call on each element.
+/// @param context The context to pass as the first argument to f.
+/// @return If the entire hashmap was iterated then 0 is returned.
+/// Otherwise if the callback function f returned positive then the positive
+/// value is returned. If the callback function returns -1, the current item
+/// is removed and iteration continues.
+static int hashmap_iterate_pairs(struct hashmap_s *const hashmap,
+ int (*f)(void *const, struct hashmap_element_s *const),
+ void *const context) HASHMAP_USED;
+
+/// @brief Get the size of the hashmap.
+/// @param hashmap The hashmap to get the size of.
+/// @return The size of the hashmap.
+static unsigned
+hashmap_num_entries(const struct hashmap_s *const hashmap) HASHMAP_USED;
+
+/// @brief Destroy the hashmap.
+/// @param hashmap The hashmap to destroy.
+static void hashmap_destroy(struct hashmap_s *const hashmap) HASHMAP_USED;
+
+static unsigned hashmap_crc32_helper(const char *const s,
+ const unsigned len) HASHMAP_USED;
+static unsigned
+hashmap_hash_helper_int_helper(const struct hashmap_s *const m,
+ const char *const keystring,
+ const unsigned len) HASHMAP_USED;
+static int hashmap_match_helper(const struct hashmap_element_s *const element,
+ const char *const key,
+ const unsigned len) HASHMAP_USED;
+static int hashmap_hash_helper(const struct hashmap_s *const m,
+ const char *const key, const unsigned len,
+ unsigned *const out_index) HASHMAP_USED;
+static int hashmap_rehash_iterator(void *const new_hash,
+ struct hashmap_element_s *const e) HASHMAP_USED;
+static int hashmap_rehash_helper(struct hashmap_s *const m) HASHMAP_USED;
+
+#if defined(__cplusplus)
+}
+#endif
+
+#if defined(__cplusplus)
+#define HASHMAP_CAST(type, x) static_cast(x)
+#define HASHMAP_PTR_CAST(type, x) reinterpret_cast(x)
+#define HASHMAP_NULL NULL
+#else
+#define HASHMAP_CAST(type, x) ((type)x)
+#define HASHMAP_PTR_CAST(type, x) ((type)x)
+#define HASHMAP_NULL 0
+#endif
+
+int hashmap_create(const unsigned initial_size,
+ struct hashmap_s *const out_hashmap) {
+ if (0 == initial_size || 0 != (initial_size & (initial_size - 1))) {
+ return 1;
+ }
+
+ out_hashmap->data =
+ HASHMAP_CAST(struct hashmap_element_s *,
+ calloc(initial_size, sizeof(struct hashmap_element_s)));
+ if (!out_hashmap->data) {
+ return 1;
+ }
+
+ out_hashmap->table_size = initial_size;
+ out_hashmap->size = 0;
+
+ return 0;
+}
+
+int hashmap_put(struct hashmap_s *const m, const char *const key,
+ const unsigned len, void *const value) {
+ unsigned int index;
+
+ /* Find a place to put our value. */
+ while (!hashmap_hash_helper(m, key, len, &index)) {
+ if (hashmap_rehash_helper(m)) {
+ return 1;
+ }
+ }
+
+ /* Set the data. */
+ m->data[index].data = value;
+ m->data[index].key = key;
+ m->data[index].key_len = len;
+ m->data[index].in_use = 1;
+ m->size++;
+
+ return 0;
+}
+
+void *hashmap_get(const struct hashmap_s *const m, const char *const key,
+ const unsigned len) {
+ unsigned int curr;
+ unsigned int i;
+
+ /* Find data location */
+ curr = hashmap_hash_helper_int_helper(m, key, len);
+
+ /* Linear probing, if necessary */
+ for (i = 0; i < HASHMAP_MAX_CHAIN_LENGTH; i++) {
+ if (m->data[curr].in_use) {
+ if (hashmap_match_helper(&m->data[curr], key, len)) {
+ return m->data[curr].data;
+ }
+ }
+
+ curr = (curr + 1) % m->table_size;
+ }
+
+ /* Not found */
+ return HASHMAP_NULL;
+}
+
+int hashmap_remove(struct hashmap_s *const m, const char *const key,
+ const unsigned len) {
+ unsigned int i;
+ unsigned int curr;
+
+ /* Find key */
+ curr = hashmap_hash_helper_int_helper(m, key, len);
+
+ /* Linear probing, if necessary */
+ for (i = 0; i < HASHMAP_MAX_CHAIN_LENGTH; i++) {
+ if (m->data[curr].in_use) {
+ if (hashmap_match_helper(&m->data[curr], key, len)) {
+ /* Blank out the fields including in_use */
+ memset(&m->data[curr], 0, sizeof(struct hashmap_element_s));
+
+ /* Reduce the size */
+ m->size--;
+ return 0;
+ }
+ }
+ curr = (curr + 1) % m->table_size;
+ }
+
+ return 1;
+}
+
+int hashmap_iterate(const struct hashmap_s *const m,
+ int (*f)(void *const, void *const), void *const context) {
+ unsigned int i;
+
+ /* Linear probing */
+ for (i = 0; i < m->table_size; i++) {
+ if (m->data[i].in_use) {
+ if (!f(context, m->data[i].data)) {
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+
+int hashmap_iterate_pairs(struct hashmap_s *const hashmap,
+ int (*f)(void *const, struct hashmap_element_s *const),
+ void *const context) {
+ unsigned int i;
+ struct hashmap_element_s *p;
+ int r;
+
+ /* Linear probing */
+ for (i = 0; i < hashmap->table_size; i++) {
+ p=&hashmap->data[i];
+ if (p->in_use) {
+ r=f(context, p);
+ switch (r)
+ {
+ case -1: /* remove item */
+ memset(p, 0, sizeof(struct hashmap_element_s));
+ hashmap->size--;
+ break;
+ case 0: /* continue iterating */
+ break;
+ default: /* early exit */
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+
+void hashmap_destroy(struct hashmap_s *const m) {
+ free(m->data);
+ memset(m, 0, sizeof(struct hashmap_s));
+}
+
+unsigned hashmap_num_entries(const struct hashmap_s *const m) {
+ return m->size;
+}
+
+unsigned hashmap_crc32_helper(const char *const s, const unsigned len) {
+ unsigned i;
+ unsigned crc32val = 0;
+
+#if defined(HASHMAP_SSE42)
+ for (i = 0; i < len; i++) {
+ crc32val = _mm_crc32_u8(crc32val, HASHMAP_CAST(unsigned char, s[i]));
+ }
+
+ return crc32val;
+#else
+ // Using polynomial 0x11EDC6F41 to match SSE 4.2's crc function.
+ static const unsigned crc32_tab[] = {
+ 0x00000000U, 0xF26B8303U, 0xE13B70F7U, 0x1350F3F4U, 0xC79A971FU,
+ 0x35F1141CU, 0x26A1E7E8U, 0xD4CA64EBU, 0x8AD958CFU, 0x78B2DBCCU,
+ 0x6BE22838U, 0x9989AB3BU, 0x4D43CFD0U, 0xBF284CD3U, 0xAC78BF27U,
+ 0x5E133C24U, 0x105EC76FU, 0xE235446CU, 0xF165B798U, 0x030E349BU,
+ 0xD7C45070U, 0x25AFD373U, 0x36FF2087U, 0xC494A384U, 0x9A879FA0U,
+ 0x68EC1CA3U, 0x7BBCEF57U, 0x89D76C54U, 0x5D1D08BFU, 0xAF768BBCU,
+ 0xBC267848U, 0x4E4DFB4BU, 0x20BD8EDEU, 0xD2D60DDDU, 0xC186FE29U,
+ 0x33ED7D2AU, 0xE72719C1U, 0x154C9AC2U, 0x061C6936U, 0xF477EA35U,
+ 0xAA64D611U, 0x580F5512U, 0x4B5FA6E6U, 0xB93425E5U, 0x6DFE410EU,
+ 0x9F95C20DU, 0x8CC531F9U, 0x7EAEB2FAU, 0x30E349B1U, 0xC288CAB2U,
+ 0xD1D83946U, 0x23B3BA45U, 0xF779DEAEU, 0x05125DADU, 0x1642AE59U,
+ 0xE4292D5AU, 0xBA3A117EU, 0x4851927DU, 0x5B016189U, 0xA96AE28AU,
+ 0x7DA08661U, 0x8FCB0562U, 0x9C9BF696U, 0x6EF07595U, 0x417B1DBCU,
+ 0xB3109EBFU, 0xA0406D4BU, 0x522BEE48U, 0x86E18AA3U, 0x748A09A0U,
+ 0x67DAFA54U, 0x95B17957U, 0xCBA24573U, 0x39C9C670U, 0x2A993584U,
+ 0xD8F2B687U, 0x0C38D26CU, 0xFE53516FU, 0xED03A29BU, 0x1F682198U,
+ 0x5125DAD3U, 0xA34E59D0U, 0xB01EAA24U, 0x42752927U, 0x96BF4DCCU,
+ 0x64D4CECFU, 0x77843D3BU, 0x85EFBE38U, 0xDBFC821CU, 0x2997011FU,
+ 0x3AC7F2EBU, 0xC8AC71E8U, 0x1C661503U, 0xEE0D9600U, 0xFD5D65F4U,
+ 0x0F36E6F7U, 0x61C69362U, 0x93AD1061U, 0x80FDE395U, 0x72966096U,
+ 0xA65C047DU, 0x5437877EU, 0x4767748AU, 0xB50CF789U, 0xEB1FCBADU,
+ 0x197448AEU, 0x0A24BB5AU, 0xF84F3859U, 0x2C855CB2U, 0xDEEEDFB1U,
+ 0xCDBE2C45U, 0x3FD5AF46U, 0x7198540DU, 0x83F3D70EU, 0x90A324FAU,
+ 0x62C8A7F9U, 0xB602C312U, 0x44694011U, 0x5739B3E5U, 0xA55230E6U,
+ 0xFB410CC2U, 0x092A8FC1U, 0x1A7A7C35U, 0xE811FF36U, 0x3CDB9BDDU,
+ 0xCEB018DEU, 0xDDE0EB2AU, 0x2F8B6829U, 0x82F63B78U, 0x709DB87BU,
+ 0x63CD4B8FU, 0x91A6C88CU, 0x456CAC67U, 0xB7072F64U, 0xA457DC90U,
+ 0x563C5F93U, 0x082F63B7U, 0xFA44E0B4U, 0xE9141340U, 0x1B7F9043U,
+ 0xCFB5F4A8U, 0x3DDE77ABU, 0x2E8E845FU, 0xDCE5075CU, 0x92A8FC17U,
+ 0x60C37F14U, 0x73938CE0U, 0x81F80FE3U, 0x55326B08U, 0xA759E80BU,
+ 0xB4091BFFU, 0x466298FCU, 0x1871A4D8U, 0xEA1A27DBU, 0xF94AD42FU,
+ 0x0B21572CU, 0xDFEB33C7U, 0x2D80B0C4U, 0x3ED04330U, 0xCCBBC033U,
+ 0xA24BB5A6U, 0x502036A5U, 0x4370C551U, 0xB11B4652U, 0x65D122B9U,
+ 0x97BAA1BAU, 0x84EA524EU, 0x7681D14DU, 0x2892ED69U, 0xDAF96E6AU,
+ 0xC9A99D9EU, 0x3BC21E9DU, 0xEF087A76U, 0x1D63F975U, 0x0E330A81U,
+ 0xFC588982U, 0xB21572C9U, 0x407EF1CAU, 0x532E023EU, 0xA145813DU,
+ 0x758FE5D6U, 0x87E466D5U, 0x94B49521U, 0x66DF1622U, 0x38CC2A06U,
+ 0xCAA7A905U, 0xD9F75AF1U, 0x2B9CD9F2U, 0xFF56BD19U, 0x0D3D3E1AU,
+ 0x1E6DCDEEU, 0xEC064EEDU, 0xC38D26C4U, 0x31E6A5C7U, 0x22B65633U,
+ 0xD0DDD530U, 0x0417B1DBU, 0xF67C32D8U, 0xE52CC12CU, 0x1747422FU,
+ 0x49547E0BU, 0xBB3FFD08U, 0xA86F0EFCU, 0x5A048DFFU, 0x8ECEE914U,
+ 0x7CA56A17U, 0x6FF599E3U, 0x9D9E1AE0U, 0xD3D3E1ABU, 0x21B862A8U,
+ 0x32E8915CU, 0xC083125FU, 0x144976B4U, 0xE622F5B7U, 0xF5720643U,
+ 0x07198540U, 0x590AB964U, 0xAB613A67U, 0xB831C993U, 0x4A5A4A90U,
+ 0x9E902E7BU, 0x6CFBAD78U, 0x7FAB5E8CU, 0x8DC0DD8FU, 0xE330A81AU,
+ 0x115B2B19U, 0x020BD8EDU, 0xF0605BEEU, 0x24AA3F05U, 0xD6C1BC06U,
+ 0xC5914FF2U, 0x37FACCF1U, 0x69E9F0D5U, 0x9B8273D6U, 0x88D28022U,
+ 0x7AB90321U, 0xAE7367CAU, 0x5C18E4C9U, 0x4F48173DU, 0xBD23943EU,
+ 0xF36E6F75U, 0x0105EC76U, 0x12551F82U, 0xE03E9C81U, 0x34F4F86AU,
+ 0xC69F7B69U, 0xD5CF889DU, 0x27A40B9EU, 0x79B737BAU, 0x8BDCB4B9U,
+ 0x988C474DU, 0x6AE7C44EU, 0xBE2DA0A5U, 0x4C4623A6U, 0x5F16D052U,
+ 0xAD7D5351U};
+
+ for (i = 0; i < len; i++) {
+ crc32val = crc32_tab[(HASHMAP_CAST(unsigned char, crc32val) ^
+ HASHMAP_CAST(unsigned char, s[i]))] ^
+ (crc32val >> 8);
+ }
+ return crc32val;
+#endif
+}
+
+unsigned hashmap_hash_helper_int_helper(const struct hashmap_s *const m,
+ const char *const keystring,
+ const unsigned len) {
+ unsigned key = hashmap_crc32_helper(keystring, len);
+
+ /* Robert Jenkins' 32 bit Mix Function */
+ key += (key << 12);
+ key ^= (key >> 22);
+ key += (key << 4);
+ key ^= (key >> 9);
+ key += (key << 10);
+ key ^= (key >> 2);
+ key += (key << 7);
+ key ^= (key >> 12);
+
+ /* Knuth's Multiplicative Method */
+ key = (key >> 3) * 2654435761;
+
+ return key % m->table_size;
+}
+
+int hashmap_match_helper(const struct hashmap_element_s *const element,
+ const char *const key, const unsigned len) {
+ return (element->key_len == len) && (0 == memcmp(element->key, key, len));
+}
+
+int hashmap_hash_helper(const struct hashmap_s *const m, const char *const key,
+ const unsigned len, unsigned *const out_index) {
+ unsigned int curr;
+ unsigned int i;
+
+ /* If full, return immediately */
+ if (m->size >= m->table_size) {
+ return 0;
+ }
+
+ /* Find the best index */
+ curr = hashmap_hash_helper_int_helper(m, key, len);
+
+ /* Linear probing */
+ for (i = 0; i < HASHMAP_MAX_CHAIN_LENGTH; i++) {
+ if (!m->data[curr].in_use) {
+ *out_index = curr;
+ return 1;
+ }
+
+ if (m->data[curr].in_use &&
+ hashmap_match_helper(&m->data[curr], key, len)) {
+ *out_index = curr;
+ return 1;
+ }
+
+ curr = (curr + 1) % m->table_size;
+ }
+
+ return 0;
+}
+
+int hashmap_rehash_iterator(void *const new_hash,
+ struct hashmap_element_s *const e) {
+ int temp=hashmap_put(HASHMAP_PTR_CAST(struct hashmap_s *, new_hash),
+ e->key, e->key_len, e->data);
+ if (0table_size;
+
+ struct hashmap_s new_hash;
+
+ int flag = hashmap_create(new_size, &new_hash);
+ if (0!=flag) {
+ return flag;
+ }
+
+ /* copy the old elements to the new table */
+ flag = hashmap_iterate_pairs(m, hashmap_rehash_iterator, HASHMAP_PTR_CAST(void *, &new_hash));
+ if (0!=flag) {
+ return flag;
+ }
+
+ hashmap_destroy(m);
+ /* put new hash into old hash structure by copying */
+ memcpy(m, &new_hash, sizeof(struct hashmap_s));
+
+ return 0;
+}
+
+#if defined(_MSC_VER)
+#pragma warning(pop)
+#elif defined(__clang__)
+#pragma clang diagnostic pop
+#endif
+
+#endif
\ No newline at end of file
diff --git a/v2/internal/ffenestri/json.c b/v2/internal/ffenestri/json.c
new file mode 100644
index 000000000..d62ff9a03
--- /dev/null
+++ b/v2/internal/ffenestri/json.c
@@ -0,0 +1,1403 @@
+// +build !windows
+
+/*
+ Copyright (C) 2011 Joseph A. Adams (joeyadams3.14159@gmail.com)
+ All rights reserved.
+
+ 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.
+
+ Source: http://git.ozlabs.org/?p=ccan;a=tree;f=ccan/json;hb=HEAD
+*/
+
+#include "json.h"
+
+#include
+#include
+#include
+#include
+#include
+
+#define out_of_memory() do { \
+ fprintf(stderr, "Out of memory.\n"); \
+ exit(EXIT_FAILURE); \
+ } while (0)
+
+/* Sadly, strdup is not portable. */
+static char *json_strdup(const char *str)
+{
+ char *ret = (char*) malloc(strlen(str) + 1);
+ if (ret == NULL)
+ out_of_memory();
+ strcpy(ret, str);
+ return ret;
+}
+
+/* String buffer */
+
+typedef struct
+{
+ char *cur;
+ char *end;
+ char *start;
+} SB;
+
+static void sb_init(SB *sb)
+{
+ sb->start = (char*) malloc(17);
+ if (sb->start == NULL)
+ out_of_memory();
+ sb->cur = sb->start;
+ sb->end = sb->start + 16;
+}
+
+/* sb and need may be evaluated multiple times. */
+#define sb_need(sb, need) do { \
+ if ((sb)->end - (sb)->cur < (need)) \
+ sb_grow(sb, need); \
+ } while (0)
+
+static void sb_grow(SB *sb, int need)
+{
+ size_t length = sb->cur - sb->start;
+ size_t alloc = sb->end - sb->start;
+
+ do {
+ alloc *= 2;
+ } while (alloc < length + need);
+
+ sb->start = (char*) realloc(sb->start, alloc + 1);
+ if (sb->start == NULL)
+ out_of_memory();
+ sb->cur = sb->start + length;
+ sb->end = sb->start + alloc;
+}
+
+static void sb_put(SB *sb, const char *bytes, int count)
+{
+ sb_need(sb, count);
+ memcpy(sb->cur, bytes, count);
+ sb->cur += count;
+}
+
+#define sb_putc(sb, c) do { \
+ if ((sb)->cur >= (sb)->end) \
+ sb_grow(sb, 1); \
+ *(sb)->cur++ = (c); \
+ } while (0)
+
+static void sb_puts(SB *sb, const char *str)
+{
+ sb_put(sb, str, strlen(str));
+}
+
+static char *sb_finish(SB *sb)
+{
+ *sb->cur = 0;
+ assert(sb->start <= sb->cur && strlen(sb->start) == (size_t)(sb->cur - sb->start));
+ return sb->start;
+}
+
+static void sb_free(SB *sb)
+{
+ free(sb->start);
+}
+
+/*
+ * Unicode helper functions
+ *
+ * These are taken from the ccan/charset module and customized a bit.
+ * Putting them here means the compiler can (choose to) inline them,
+ * and it keeps ccan/json from having a dependency.
+ */
+
+/*
+ * Type for Unicode codepoints.
+ * We need our own because wchar_t might be 16 bits.
+ */
+typedef uint32_t uchar_t;
+
+/*
+ * Validate a single UTF-8 character starting at @s.
+ * The string must be null-terminated.
+ *
+ * If it's valid, return its length (1 thru 4).
+ * If it's invalid or clipped, return 0.
+ *
+ * This function implements the syntax given in RFC3629, which is
+ * the same as that given in The Unicode Standard, Version 6.0.
+ *
+ * It has the following properties:
+ *
+ * * All codepoints U+0000..U+10FFFF may be encoded,
+ * except for U+D800..U+DFFF, which are reserved
+ * for UTF-16 surrogate pair encoding.
+ * * UTF-8 byte sequences longer than 4 bytes are not permitted,
+ * as they exceed the range of Unicode.
+ * * The sixty-six Unicode "non-characters" are permitted
+ * (namely, U+FDD0..U+FDEF, U+xxFFFE, and U+xxFFFF).
+ */
+static int utf8_validate_cz(const char *s)
+{
+ unsigned char c = *s++;
+
+ if (c <= 0x7F) { /* 00..7F */
+ return 1;
+ } else if (c <= 0xC1) { /* 80..C1 */
+ /* Disallow overlong 2-byte sequence. */
+ return 0;
+ } else if (c <= 0xDF) { /* C2..DF */
+ /* Make sure subsequent byte is in the range 0x80..0xBF. */
+ if (((unsigned char)*s++ & 0xC0) != 0x80)
+ return 0;
+
+ return 2;
+ } else if (c <= 0xEF) { /* E0..EF */
+ /* Disallow overlong 3-byte sequence. */
+ if (c == 0xE0 && (unsigned char)*s < 0xA0)
+ return 0;
+
+ /* Disallow U+D800..U+DFFF. */
+ if (c == 0xED && (unsigned char)*s > 0x9F)
+ return 0;
+
+ /* Make sure subsequent bytes are in the range 0x80..0xBF. */
+ if (((unsigned char)*s++ & 0xC0) != 0x80)
+ return 0;
+ if (((unsigned char)*s++ & 0xC0) != 0x80)
+ return 0;
+
+ return 3;
+ } else if (c <= 0xF4) { /* F0..F4 */
+ /* Disallow overlong 4-byte sequence. */
+ if (c == 0xF0 && (unsigned char)*s < 0x90)
+ return 0;
+
+ /* Disallow codepoints beyond U+10FFFF. */
+ if (c == 0xF4 && (unsigned char)*s > 0x8F)
+ return 0;
+
+ /* Make sure subsequent bytes are in the range 0x80..0xBF. */
+ if (((unsigned char)*s++ & 0xC0) != 0x80)
+ return 0;
+ if (((unsigned char)*s++ & 0xC0) != 0x80)
+ return 0;
+ if (((unsigned char)*s++ & 0xC0) != 0x80)
+ return 0;
+
+ return 4;
+ } else { /* F5..FF */
+ return 0;
+ }
+}
+
+/* Validate a null-terminated UTF-8 string. */
+static bool utf8_validate(const char *s)
+{
+ int len;
+
+ for (; *s != 0; s += len) {
+ len = utf8_validate_cz(s);
+ if (len == 0)
+ return false;
+ }
+
+ return true;
+}
+
+/*
+ * Read a single UTF-8 character starting at @s,
+ * returning the length, in bytes, of the character read.
+ *
+ * This function assumes input is valid UTF-8,
+ * and that there are enough characters in front of @s.
+ */
+static int utf8_read_char(const char *s, uchar_t *out)
+{
+ const unsigned char *c = (const unsigned char*) s;
+
+ assert(utf8_validate_cz(s));
+
+ if (c[0] <= 0x7F) {
+ /* 00..7F */
+ *out = c[0];
+ return 1;
+ } else if (c[0] <= 0xDF) {
+ /* C2..DF (unless input is invalid) */
+ *out = ((uchar_t)c[0] & 0x1F) << 6 |
+ ((uchar_t)c[1] & 0x3F);
+ return 2;
+ } else if (c[0] <= 0xEF) {
+ /* E0..EF */
+ *out = ((uchar_t)c[0] & 0xF) << 12 |
+ ((uchar_t)c[1] & 0x3F) << 6 |
+ ((uchar_t)c[2] & 0x3F);
+ return 3;
+ } else {
+ /* F0..F4 (unless input is invalid) */
+ *out = ((uchar_t)c[0] & 0x7) << 18 |
+ ((uchar_t)c[1] & 0x3F) << 12 |
+ ((uchar_t)c[2] & 0x3F) << 6 |
+ ((uchar_t)c[3] & 0x3F);
+ return 4;
+ }
+}
+
+/*
+ * Write a single UTF-8 character to @s,
+ * returning the length, in bytes, of the character written.
+ *
+ * @unicode must be U+0000..U+10FFFF, but not U+D800..U+DFFF.
+ *
+ * This function will write up to 4 bytes to @out.
+ */
+static int utf8_write_char(uchar_t unicode, char *out)
+{
+ unsigned char *o = (unsigned char*) out;
+
+ assert(unicode <= 0x10FFFF && !(unicode >= 0xD800 && unicode <= 0xDFFF));
+
+ if (unicode <= 0x7F) {
+ /* U+0000..U+007F */
+ *o++ = unicode;
+ return 1;
+ } else if (unicode <= 0x7FF) {
+ /* U+0080..U+07FF */
+ *o++ = 0xC0 | unicode >> 6;
+ *o++ = 0x80 | (unicode & 0x3F);
+ return 2;
+ } else if (unicode <= 0xFFFF) {
+ /* U+0800..U+FFFF */
+ *o++ = 0xE0 | unicode >> 12;
+ *o++ = 0x80 | (unicode >> 6 & 0x3F);
+ *o++ = 0x80 | (unicode & 0x3F);
+ return 3;
+ } else {
+ /* U+10000..U+10FFFF */
+ *o++ = 0xF0 | unicode >> 18;
+ *o++ = 0x80 | (unicode >> 12 & 0x3F);
+ *o++ = 0x80 | (unicode >> 6 & 0x3F);
+ *o++ = 0x80 | (unicode & 0x3F);
+ return 4;
+ }
+}
+
+/*
+ * Compute the Unicode codepoint of a UTF-16 surrogate pair.
+ *
+ * @uc should be 0xD800..0xDBFF, and @lc should be 0xDC00..0xDFFF.
+ * If they aren't, this function returns false.
+ */
+static bool from_surrogate_pair(uint16_t uc, uint16_t lc, uchar_t *unicode)
+{
+ if (uc >= 0xD800 && uc <= 0xDBFF && lc >= 0xDC00 && lc <= 0xDFFF) {
+ *unicode = 0x10000 + ((((uchar_t)uc & 0x3FF) << 10) | (lc & 0x3FF));
+ return true;
+ } else {
+ return false;
+ }
+}
+
+/*
+ * Construct a UTF-16 surrogate pair given a Unicode codepoint.
+ *
+ * @unicode must be U+10000..U+10FFFF.
+ */
+static void to_surrogate_pair(uchar_t unicode, uint16_t *uc, uint16_t *lc)
+{
+ uchar_t n;
+
+ assert(unicode >= 0x10000 && unicode <= 0x10FFFF);
+
+ n = unicode - 0x10000;
+ *uc = ((n >> 10) & 0x3FF) | 0xD800;
+ *lc = (n & 0x3FF) | 0xDC00;
+}
+
+#define is_space(c) ((c) == '\t' || (c) == '\n' || (c) == '\r' || (c) == ' ')
+#define is_digit(c) ((c) >= '0' && (c) <= '9')
+
+static bool parse_value (const char **sp, JsonNode **out);
+static bool parse_string (const char **sp, char **out);
+static bool parse_number (const char **sp, double *out);
+static bool parse_array (const char **sp, JsonNode **out);
+static bool parse_object (const char **sp, JsonNode **out);
+static bool parse_hex16 (const char **sp, uint16_t *out);
+
+static bool expect_literal (const char **sp, const char *str);
+static void skip_space (const char **sp);
+
+static void emit_value (SB *out, const JsonNode *node);
+static void emit_value_indented (SB *out, const JsonNode *node, const char *space, int indent_level);
+static void emit_string (SB *out, const char *str);
+static void emit_number (SB *out, double num);
+static void emit_array (SB *out, const JsonNode *array);
+static void emit_array_indented (SB *out, const JsonNode *array, const char *space, int indent_level);
+static void emit_object (SB *out, const JsonNode *object);
+static void emit_object_indented (SB *out, const JsonNode *object, const char *space, int indent_level);
+
+static int write_hex16(char *out, uint16_t val);
+
+static JsonNode *mknode(JsonTag tag);
+static void append_node(JsonNode *parent, JsonNode *child);
+static void prepend_node(JsonNode *parent, JsonNode *child);
+static void append_member(JsonNode *object, char *key, JsonNode *value);
+
+/* Assertion-friendly validity checks */
+static bool tag_is_valid(unsigned int tag);
+static bool number_is_valid(const char *num);
+
+JsonNode *json_decode(const char *json)
+{
+ const char *s = json;
+ JsonNode *ret;
+
+ skip_space(&s);
+ if (!parse_value(&s, &ret))
+ return NULL;
+
+ skip_space(&s);
+ if (*s != 0) {
+ json_delete(ret);
+ return NULL;
+ }
+
+ return ret;
+}
+
+char *json_encode(const JsonNode *node)
+{
+ return json_stringify(node, NULL);
+}
+
+char *json_encode_string(const char *str)
+{
+ SB sb;
+ sb_init(&sb);
+
+ emit_string(&sb, str);
+
+ return sb_finish(&sb);
+}
+
+char *json_stringify(const JsonNode *node, const char *space)
+{
+ SB sb;
+ sb_init(&sb);
+
+ if (space != NULL)
+ emit_value_indented(&sb, node, space, 0);
+ else
+ emit_value(&sb, node);
+
+ return sb_finish(&sb);
+}
+
+void json_delete(JsonNode *node)
+{
+ if (node != NULL) {
+ json_remove_from_parent(node);
+
+ switch (node->tag) {
+ case JSON_STRING:
+ free(node->string_);
+ break;
+ case JSON_ARRAY:
+ case JSON_OBJECT:
+ {
+ JsonNode *child, *next;
+ for (child = node->children.head; child != NULL; child = next) {
+ next = child->next;
+ json_delete(child);
+ }
+ break;
+ }
+ default:;
+ }
+
+ free(node);
+ }
+}
+
+bool json_validate(const char *json)
+{
+ const char *s = json;
+
+ skip_space(&s);
+ if (!parse_value(&s, NULL))
+ return false;
+
+ skip_space(&s);
+ if (*s != 0)
+ return false;
+
+ return true;
+}
+
+// We return the number of elements or -1 if there was a problem
+int json_array_length(JsonNode *array) {
+
+ int result = 0;
+
+ // The node should not be null and it should be an array
+ if (array == NULL || array->tag != JSON_ARRAY)
+ return -1;
+
+ // Loop and count!
+ JsonNode *element;
+ json_foreach(element, array) {
+ result++;
+ }
+
+ return result;
+}
+
+JsonNode *json_find_element(JsonNode *array, int index)
+{
+ JsonNode *element;
+ int i = 0;
+
+ if (array == NULL || array->tag != JSON_ARRAY)
+ return NULL;
+
+ json_foreach(element, array) {
+ if (i == index)
+ return element;
+ i++;
+ }
+
+ return NULL;
+}
+
+JsonNode *json_find_member(JsonNode *object, const char *name)
+{
+ JsonNode *member;
+
+ if (object == NULL || object->tag != JSON_OBJECT)
+ return NULL;
+
+ json_foreach(member, object)
+ if (strcmp(member->key, name) == 0)
+ return member;
+
+ return NULL;
+}
+
+JsonNode *json_first_child(const JsonNode *node)
+{
+ if (node != NULL && (node->tag == JSON_ARRAY || node->tag == JSON_OBJECT))
+ return node->children.head;
+ return NULL;
+}
+
+static JsonNode *mknode(JsonTag tag)
+{
+ JsonNode *ret = (JsonNode*) calloc(1, sizeof(JsonNode));
+ if (ret == NULL)
+ out_of_memory();
+ ret->tag = tag;
+ return ret;
+}
+
+JsonNode *json_mknull(void)
+{
+ return mknode(JSON_NULL);
+}
+
+JsonNode *json_mkbool(bool b)
+{
+ JsonNode *ret = mknode(JSON_BOOL);
+ ret->bool_ = b;
+ return ret;
+}
+
+static JsonNode *mkstring(char *s)
+{
+ JsonNode *ret = mknode(JSON_STRING);
+ ret->string_ = s;
+ return ret;
+}
+
+JsonNode *json_mkstring(const char *s)
+{
+ return mkstring(json_strdup(s));
+}
+
+JsonNode *json_mknumber(double n)
+{
+ JsonNode *node = mknode(JSON_NUMBER);
+ node->number_ = n;
+ return node;
+}
+
+JsonNode *json_mkarray(void)
+{
+ return mknode(JSON_ARRAY);
+}
+
+JsonNode *json_mkobject(void)
+{
+ return mknode(JSON_OBJECT);
+}
+
+static void append_node(JsonNode *parent, JsonNode *child)
+{
+ child->parent = parent;
+ child->prev = parent->children.tail;
+ child->next = NULL;
+
+ if (parent->children.tail != NULL)
+ parent->children.tail->next = child;
+ else
+ parent->children.head = child;
+ parent->children.tail = child;
+}
+
+static void prepend_node(JsonNode *parent, JsonNode *child)
+{
+ child->parent = parent;
+ child->prev = NULL;
+ child->next = parent->children.head;
+
+ if (parent->children.head != NULL)
+ parent->children.head->prev = child;
+ else
+ parent->children.tail = child;
+ parent->children.head = child;
+}
+
+static void append_member(JsonNode *object, char *key, JsonNode *value)
+{
+ value->key = key;
+ append_node(object, value);
+}
+
+void json_append_element(JsonNode *array, JsonNode *element)
+{
+ assert(array->tag == JSON_ARRAY);
+ assert(element->parent == NULL);
+
+ append_node(array, element);
+}
+
+void json_prepend_element(JsonNode *array, JsonNode *element)
+{
+ assert(array->tag == JSON_ARRAY);
+ assert(element->parent == NULL);
+
+ prepend_node(array, element);
+}
+
+void json_append_member(JsonNode *object, const char *key, JsonNode *value)
+{
+ assert(object->tag == JSON_OBJECT);
+ assert(value->parent == NULL);
+
+ append_member(object, json_strdup(key), value);
+}
+
+void json_prepend_member(JsonNode *object, const char *key, JsonNode *value)
+{
+ assert(object->tag == JSON_OBJECT);
+ assert(value->parent == NULL);
+
+ value->key = json_strdup(key);
+ prepend_node(object, value);
+}
+
+void json_remove_from_parent(JsonNode *node)
+{
+ JsonNode *parent = node->parent;
+
+ if (parent != NULL) {
+ if (node->prev != NULL)
+ node->prev->next = node->next;
+ else
+ parent->children.head = node->next;
+ if (node->next != NULL)
+ node->next->prev = node->prev;
+ else
+ parent->children.tail = node->prev;
+
+ free(node->key);
+
+ node->parent = NULL;
+ node->prev = node->next = NULL;
+ node->key = NULL;
+ }
+}
+
+static bool parse_value(const char **sp, JsonNode **out)
+{
+ const char *s = *sp;
+
+ switch (*s) {
+ case 'n':
+ if (expect_literal(&s, "null")) {
+ if (out)
+ *out = json_mknull();
+ *sp = s;
+ return true;
+ }
+ return false;
+
+ case 'f':
+ if (expect_literal(&s, "false")) {
+ if (out)
+ *out = json_mkbool(false);
+ *sp = s;
+ return true;
+ }
+ return false;
+
+ case 't':
+ if (expect_literal(&s, "true")) {
+ if (out)
+ *out = json_mkbool(true);
+ *sp = s;
+ return true;
+ }
+ return false;
+
+ case '"': {
+ char *str;
+ if (parse_string(&s, out ? &str : NULL)) {
+ if (out)
+ *out = mkstring(str);
+ *sp = s;
+ return true;
+ }
+ return false;
+ }
+
+ case '[':
+ if (parse_array(&s, out)) {
+ *sp = s;
+ return true;
+ }
+ return false;
+
+ case '{':
+ if (parse_object(&s, out)) {
+ *sp = s;
+ return true;
+ }
+ return false;
+
+ default: {
+ double num;
+ if (parse_number(&s, out ? &num : NULL)) {
+ if (out)
+ *out = json_mknumber(num);
+ *sp = s;
+ return true;
+ }
+ return false;
+ }
+ }
+}
+
+static bool parse_array(const char **sp, JsonNode **out)
+{
+ const char *s = *sp;
+ JsonNode *ret = out ? json_mkarray() : NULL;
+ JsonNode *element;
+
+ if (*s++ != '[')
+ goto failure;
+ skip_space(&s);
+
+ if (*s == ']') {
+ s++;
+ goto success;
+ }
+
+ for (;;) {
+ if (!parse_value(&s, out ? &element : NULL))
+ goto failure;
+ skip_space(&s);
+
+ if (out)
+ json_append_element(ret, element);
+
+ if (*s == ']') {
+ s++;
+ goto success;
+ }
+
+ if (*s++ != ',')
+ goto failure;
+ skip_space(&s);
+ }
+
+success:
+ *sp = s;
+ if (out)
+ *out = ret;
+ return true;
+
+failure:
+ json_delete(ret);
+ return false;
+}
+
+static bool parse_object(const char **sp, JsonNode **out)
+{
+ const char *s = *sp;
+ JsonNode *ret = out ? json_mkobject() : NULL;
+ char *key;
+ JsonNode *value;
+
+ if (*s++ != '{')
+ goto failure;
+ skip_space(&s);
+
+ if (*s == '}') {
+ s++;
+ goto success;
+ }
+
+ for (;;) {
+ if (!parse_string(&s, out ? &key : NULL))
+ goto failure;
+ skip_space(&s);
+
+ if (*s++ != ':')
+ goto failure_free_key;
+ skip_space(&s);
+
+ if (!parse_value(&s, out ? &value : NULL))
+ goto failure_free_key;
+ skip_space(&s);
+
+ if (out)
+ append_member(ret, key, value);
+
+ if (*s == '}') {
+ s++;
+ goto success;
+ }
+
+ if (*s++ != ',')
+ goto failure;
+ skip_space(&s);
+ }
+
+success:
+ *sp = s;
+ if (out)
+ *out = ret;
+ return true;
+
+failure_free_key:
+ if (out)
+ free(key);
+failure:
+ json_delete(ret);
+ return false;
+}
+
+bool parse_string(const char **sp, char **out)
+{
+ const char *s = *sp;
+ SB sb;
+ char throwaway_buffer[4];
+ /* enough space for a UTF-8 character */
+ char *b;
+
+ if (*s++ != '"')
+ return false;
+
+ if (out) {
+ sb_init(&sb);
+ sb_need(&sb, 4);
+ b = sb.cur;
+ } else {
+ b = throwaway_buffer;
+ }
+
+ while (*s != '"') {
+ unsigned char c = *s++;
+
+ /* Parse next character, and write it to b. */
+ if (c == '\\') {
+ c = *s++;
+ switch (c) {
+ case '"':
+ case '\\':
+ case '/':
+ *b++ = c;
+ break;
+ case 'b':
+ *b++ = '\b';
+ break;
+ case 'f':
+ *b++ = '\f';
+ break;
+ case 'n':
+ *b++ = '\n';
+ break;
+ case 'r':
+ *b++ = '\r';
+ break;
+ case 't':
+ *b++ = '\t';
+ break;
+ case 'u':
+ {
+ uint16_t uc, lc;
+ uchar_t unicode;
+
+ if (!parse_hex16(&s, &uc))
+ goto failed;
+
+ if (uc >= 0xD800 && uc <= 0xDFFF) {
+ /* Handle UTF-16 surrogate pair. */
+ if (*s++ != '\\' || *s++ != 'u' || !parse_hex16(&s, &lc))
+ goto failed; /* Incomplete surrogate pair. */
+ if (!from_surrogate_pair(uc, lc, &unicode))
+ goto failed; /* Invalid surrogate pair. */
+ } else if (uc == 0) {
+ /* Disallow "\u0000". */
+ goto failed;
+ } else {
+ unicode = uc;
+ }
+
+ b += utf8_write_char(unicode, b);
+ break;
+ }
+ default:
+ /* Invalid escape */
+ goto failed;
+ }
+ } else if (c <= 0x1F) {
+ /* Control characters are not allowed in string literals. */
+ goto failed;
+ } else {
+ /* Validate and echo a UTF-8 character. */
+ int len;
+
+ s--;
+ len = utf8_validate_cz(s);
+ if (len == 0)
+ goto failed; /* Invalid UTF-8 character. */
+
+ while (len--)
+ *b++ = *s++;
+ }
+
+ /*
+ * Update sb to know about the new bytes,
+ * and set up b to write another character.
+ */
+ if (out) {
+ sb.cur = b;
+ sb_need(&sb, 4);
+ b = sb.cur;
+ } else {
+ b = throwaway_buffer;
+ }
+ }
+ s++;
+
+ if (out)
+ *out = sb_finish(&sb);
+ *sp = s;
+ return true;
+
+failed:
+ if (out)
+ sb_free(&sb);
+ return false;
+}
+
+/*
+ * The JSON spec says that a number shall follow this precise pattern
+ * (spaces and quotes added for readability):
+ * '-'? (0 | [1-9][0-9]*) ('.' [0-9]+)? ([Ee] [+-]? [0-9]+)?
+ *
+ * However, some JSON parsers are more liberal. For instance, PHP accepts
+ * '.5' and '1.'. JSON.parse accepts '+3'.
+ *
+ * This function takes the strict approach.
+ */
+bool parse_number(const char **sp, double *out)
+{
+ const char *s = *sp;
+
+ /* '-'? */
+ if (*s == '-')
+ s++;
+
+ /* (0 | [1-9][0-9]*) */
+ if (*s == '0') {
+ s++;
+ } else {
+ if (!is_digit(*s))
+ return false;
+ do {
+ s++;
+ } while (is_digit(*s));
+ }
+
+ /* ('.' [0-9]+)? */
+ if (*s == '.') {
+ s++;
+ if (!is_digit(*s))
+ return false;
+ do {
+ s++;
+ } while (is_digit(*s));
+ }
+
+ /* ([Ee] [+-]? [0-9]+)? */
+ if (*s == 'E' || *s == 'e') {
+ s++;
+ if (*s == '+' || *s == '-')
+ s++;
+ if (!is_digit(*s))
+ return false;
+ do {
+ s++;
+ } while (is_digit(*s));
+ }
+
+ if (out)
+ *out = strtod(*sp, NULL);
+
+ *sp = s;
+ return true;
+}
+
+static void skip_space(const char **sp)
+{
+ const char *s = *sp;
+ while (is_space(*s))
+ s++;
+ *sp = s;
+}
+
+static void emit_value(SB *out, const JsonNode *node)
+{
+ assert(tag_is_valid(node->tag));
+ switch (node->tag) {
+ case JSON_NULL:
+ sb_puts(out, "null");
+ break;
+ case JSON_BOOL:
+ sb_puts(out, node->bool_ ? "true" : "false");
+ break;
+ case JSON_STRING:
+ emit_string(out, node->string_);
+ break;
+ case JSON_NUMBER:
+ emit_number(out, node->number_);
+ break;
+ case JSON_ARRAY:
+ emit_array(out, node);
+ break;
+ case JSON_OBJECT:
+ emit_object(out, node);
+ break;
+ default:
+ assert(false);
+ }
+}
+
+void emit_value_indented(SB *out, const JsonNode *node, const char *space, int indent_level)
+{
+ assert(tag_is_valid(node->tag));
+ switch (node->tag) {
+ case JSON_NULL:
+ sb_puts(out, "null");
+ break;
+ case JSON_BOOL:
+ sb_puts(out, node->bool_ ? "true" : "false");
+ break;
+ case JSON_STRING:
+ emit_string(out, node->string_);
+ break;
+ case JSON_NUMBER:
+ emit_number(out, node->number_);
+ break;
+ case JSON_ARRAY:
+ emit_array_indented(out, node, space, indent_level);
+ break;
+ case JSON_OBJECT:
+ emit_object_indented(out, node, space, indent_level);
+ break;
+ default:
+ assert(false);
+ }
+}
+
+static void emit_array(SB *out, const JsonNode *array)
+{
+ const JsonNode *element;
+
+ sb_putc(out, '[');
+ json_foreach(element, array) {
+ emit_value(out, element);
+ if (element->next != NULL)
+ sb_putc(out, ',');
+ }
+ sb_putc(out, ']');
+}
+
+static void emit_array_indented(SB *out, const JsonNode *array, const char *space, int indent_level)
+{
+ const JsonNode *element = array->children.head;
+ int i;
+
+ if (element == NULL) {
+ sb_puts(out, "[]");
+ return;
+ }
+
+ sb_puts(out, "[\n");
+ while (element != NULL) {
+ for (i = 0; i < indent_level + 1; i++)
+ sb_puts(out, space);
+ emit_value_indented(out, element, space, indent_level + 1);
+
+ element = element->next;
+ sb_puts(out, element != NULL ? ",\n" : "\n");
+ }
+ for (i = 0; i < indent_level; i++)
+ sb_puts(out, space);
+ sb_putc(out, ']');
+}
+
+static void emit_object(SB *out, const JsonNode *object)
+{
+ const JsonNode *member;
+
+ sb_putc(out, '{');
+ json_foreach(member, object) {
+ emit_string(out, member->key);
+ sb_putc(out, ':');
+ emit_value(out, member);
+ if (member->next != NULL)
+ sb_putc(out, ',');
+ }
+ sb_putc(out, '}');
+}
+
+static void emit_object_indented(SB *out, const JsonNode *object, const char *space, int indent_level)
+{
+ const JsonNode *member = object->children.head;
+ int i;
+
+ if (member == NULL) {
+ sb_puts(out, "{}");
+ return;
+ }
+
+ sb_puts(out, "{\n");
+ while (member != NULL) {
+ for (i = 0; i < indent_level + 1; i++)
+ sb_puts(out, space);
+ emit_string(out, member->key);
+ sb_puts(out, ": ");
+ emit_value_indented(out, member, space, indent_level + 1);
+
+ member = member->next;
+ sb_puts(out, member != NULL ? ",\n" : "\n");
+ }
+ for (i = 0; i < indent_level; i++)
+ sb_puts(out, space);
+ sb_putc(out, '}');
+}
+
+void emit_string(SB *out, const char *str)
+{
+ bool escape_unicode = false;
+ const char *s = str;
+ char *b;
+
+ assert(utf8_validate(str));
+
+ /*
+ * 14 bytes is enough space to write up to two
+ * \uXXXX escapes and two quotation marks.
+ */
+ sb_need(out, 14);
+ b = out->cur;
+
+ *b++ = '"';
+ while (*s != 0) {
+ unsigned char c = *s++;
+
+ /* Encode the next character, and write it to b. */
+ switch (c) {
+ case '"':
+ *b++ = '\\';
+ *b++ = '"';
+ break;
+ case '\\':
+ *b++ = '\\';
+ *b++ = '\\';
+ break;
+ case '\b':
+ *b++ = '\\';
+ *b++ = 'b';
+ break;
+ case '\f':
+ *b++ = '\\';
+ *b++ = 'f';
+ break;
+ case '\n':
+ *b++ = '\\';
+ *b++ = 'n';
+ break;
+ case '\r':
+ *b++ = '\\';
+ *b++ = 'r';
+ break;
+ case '\t':
+ *b++ = '\\';
+ *b++ = 't';
+ break;
+ default: {
+ int len;
+
+ s--;
+ len = utf8_validate_cz(s);
+
+ if (len == 0) {
+ /*
+ * Handle invalid UTF-8 character gracefully in production
+ * by writing a replacement character (U+FFFD)
+ * and skipping a single byte.
+ *
+ * This should never happen when assertions are enabled
+ * due to the assertion at the beginning of this function.
+ */
+ assert(false);
+ if (escape_unicode) {
+ strcpy(b, "\\uFFFD");
+ b += 6;
+ } else {
+ *b++ = 0xEF;
+ *b++ = 0xBF;
+ *b++ = 0xBD;
+ }
+ s++;
+ } else if (c < 0x1F || (c >= 0x80 && escape_unicode)) {
+ /* Encode using \u.... */
+ uint32_t unicode;
+
+ s += utf8_read_char(s, &unicode);
+
+ if (unicode <= 0xFFFF) {
+ *b++ = '\\';
+ *b++ = 'u';
+ b += write_hex16(b, unicode);
+ } else {
+ /* Produce a surrogate pair. */
+ uint16_t uc, lc;
+ assert(unicode <= 0x10FFFF);
+ to_surrogate_pair(unicode, &uc, &lc);
+ *b++ = '\\';
+ *b++ = 'u';
+ b += write_hex16(b, uc);
+ *b++ = '\\';
+ *b++ = 'u';
+ b += write_hex16(b, lc);
+ }
+ } else {
+ /* Write the character directly. */
+ while (len--)
+ *b++ = *s++;
+ }
+
+ break;
+ }
+ }
+
+ /*
+ * Update *out to know about the new bytes,
+ * and set up b to write another encoded character.
+ */
+ out->cur = b;
+ sb_need(out, 14);
+ b = out->cur;
+ }
+ *b++ = '"';
+
+ out->cur = b;
+}
+
+static void emit_number(SB *out, double num)
+{
+ /*
+ * This isn't exactly how JavaScript renders numbers,
+ * but it should produce valid JSON for reasonable numbers
+ * preserve precision well enough, and avoid some oddities
+ * like 0.3 -> 0.299999999999999988898 .
+ */
+ char buf[64];
+ sprintf(buf, "%.16g", num);
+
+ if (number_is_valid(buf))
+ sb_puts(out, buf);
+ else
+ sb_puts(out, "null");
+}
+
+static bool tag_is_valid(unsigned int tag)
+{
+ return (/* tag >= JSON_NULL && */ tag <= JSON_OBJECT);
+}
+
+static bool number_is_valid(const char *num)
+{
+ return (parse_number(&num, NULL) && *num == '\0');
+}
+
+static bool expect_literal(const char **sp, const char *str)
+{
+ const char *s = *sp;
+
+ while (*str != '\0')
+ if (*s++ != *str++)
+ return false;
+
+ *sp = s;
+ return true;
+}
+
+/*
+ * Parses exactly 4 hex characters (capital or lowercase).
+ * Fails if any input chars are not [0-9A-Fa-f].
+ */
+static bool parse_hex16(const char **sp, uint16_t *out)
+{
+ const char *s = *sp;
+ uint16_t ret = 0;
+ uint16_t i;
+ uint16_t tmp;
+ char c;
+
+ for (i = 0; i < 4; i++) {
+ c = *s++;
+ if (c >= '0' && c <= '9')
+ tmp = c - '0';
+ else if (c >= 'A' && c <= 'F')
+ tmp = c - 'A' + 10;
+ else if (c >= 'a' && c <= 'f')
+ tmp = c - 'a' + 10;
+ else
+ return false;
+
+ ret <<= 4;
+ ret += tmp;
+ }
+
+ if (out)
+ *out = ret;
+ *sp = s;
+ return true;
+}
+
+/*
+ * Encodes a 16-bit number into hexadecimal,
+ * writing exactly 4 hex chars.
+ */
+static int write_hex16(char *out, uint16_t val)
+{
+ const char *hex = "0123456789ABCDEF";
+
+ *out++ = hex[(val >> 12) & 0xF];
+ *out++ = hex[(val >> 8) & 0xF];
+ *out++ = hex[(val >> 4) & 0xF];
+ *out++ = hex[ val & 0xF];
+
+ return 4;
+}
+
+bool json_check(const JsonNode *node, char errmsg[256])
+{
+ #define problem(...) do { \
+ if (errmsg != NULL) \
+ snprintf(errmsg, 256, __VA_ARGS__); \
+ return false; \
+ } while (0)
+
+ if (node->key != NULL && !utf8_validate(node->key))
+ problem("key contains invalid UTF-8");
+
+ if (!tag_is_valid(node->tag))
+ problem("tag is invalid (%u)", node->tag);
+
+ if (node->tag == JSON_BOOL) {
+ if (node->bool_ != false && node->bool_ != true)
+ problem("bool_ is neither false (%d) nor true (%d)", (int)false, (int)true);
+ } else if (node->tag == JSON_STRING) {
+ if (node->string_ == NULL)
+ problem("string_ is NULL");
+ if (!utf8_validate(node->string_))
+ problem("string_ contains invalid UTF-8");
+ } else if (node->tag == JSON_ARRAY || node->tag == JSON_OBJECT) {
+ JsonNode *head = node->children.head;
+ JsonNode *tail = node->children.tail;
+
+ if (head == NULL || tail == NULL) {
+ if (head != NULL)
+ problem("tail is NULL, but head is not");
+ if (tail != NULL)
+ problem("head is NULL, but tail is not");
+ } else {
+ JsonNode *child;
+ JsonNode *last = NULL;
+
+ if (head->prev != NULL)
+ problem("First child's prev pointer is not NULL");
+
+ for (child = head; child != NULL; last = child, child = child->next) {
+ if (child == node)
+ problem("node is its own child");
+ if (child->next == child)
+ problem("child->next == child (cycle)");
+ if (child->next == head)
+ problem("child->next == head (cycle)");
+
+ if (child->parent != node)
+ problem("child does not point back to parent");
+ if (child->next != NULL && child->next->prev != child)
+ problem("child->next does not point back to child");
+
+ if (node->tag == JSON_ARRAY && child->key != NULL)
+ problem("Array element's key is not NULL");
+ if (node->tag == JSON_OBJECT && child->key == NULL)
+ problem("Object member's key is NULL");
+
+ if (!json_check(child, errmsg))
+ return false;
+ }
+
+ if (last != tail)
+ problem("tail does not match pointer found by starting at head and following next links");
+ }
+ }
+
+ return true;
+
+ #undef problem
+}
\ No newline at end of file
diff --git a/v2/internal/ffenestri/json.h b/v2/internal/ffenestri/json.h
new file mode 100644
index 000000000..aaf711f8a
--- /dev/null
+++ b/v2/internal/ffenestri/json.h
@@ -0,0 +1,122 @@
+/*
+ Copyright (C) 2011 Joseph A. Adams (joeyadams3.14159@gmail.com)
+ All rights reserved.
+
+ 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.
+
+ Source: http://git.ozlabs.org/?p=ccan;a=tree;f=ccan/json;hb=HEAD
+*/
+
+#ifndef CCAN_JSON_H
+#define CCAN_JSON_H
+
+#include
+#include
+
+typedef enum {
+ JSON_NULL,
+ JSON_BOOL,
+ JSON_STRING,
+ JSON_NUMBER,
+ JSON_ARRAY,
+ JSON_OBJECT,
+} JsonTag;
+
+typedef struct JsonNode JsonNode;
+
+struct JsonNode
+{
+ /* only if parent is an object or array (NULL otherwise) */
+ JsonNode *parent;
+ JsonNode *prev, *next;
+
+ /* only if parent is an object (NULL otherwise) */
+ char *key; /* Must be valid UTF-8. */
+
+ JsonTag tag;
+ union {
+ /* JSON_BOOL */
+ bool bool_;
+
+ /* JSON_STRING */
+ char *string_; /* Must be valid UTF-8. */
+
+ /* JSON_NUMBER */
+ double number_;
+
+ /* JSON_ARRAY */
+ /* JSON_OBJECT */
+ struct {
+ JsonNode *head, *tail;
+ } children;
+ };
+};
+
+/*** Encoding, decoding, and validation ***/
+
+JsonNode *json_decode (const char *json);
+char *json_encode (const JsonNode *node);
+char *json_encode_string (const char *str);
+char *json_stringify (const JsonNode *node, const char *space);
+void json_delete (JsonNode *node);
+
+bool json_validate (const char *json);
+
+/*** Lookup and traversal ***/
+
+JsonNode *json_find_element (JsonNode *array, int index);
+JsonNode *json_find_member (JsonNode *object, const char *key);
+
+JsonNode *json_first_child (const JsonNode *node);
+
+#define json_foreach(i, object_or_array) \
+ for ((i) = json_first_child(object_or_array); \
+ (i) != NULL; \
+ (i) = (i)->next)
+
+/*** Construction and manipulation ***/
+
+JsonNode *json_mknull(void);
+JsonNode *json_mkbool(bool b);
+JsonNode *json_mkstring(const char *s);
+JsonNode *json_mknumber(double n);
+JsonNode *json_mkarray(void);
+JsonNode *json_mkobject(void);
+
+void json_append_element(JsonNode *array, JsonNode *element);
+void json_prepend_element(JsonNode *array, JsonNode *element);
+void json_append_member(JsonNode *object, const char *key, JsonNode *value);
+void json_prepend_member(JsonNode *object, const char *key, JsonNode *value);
+
+void json_remove_from_parent(JsonNode *node);
+
+/*** Debugging ***/
+
+/*
+ * Look for structure and encoding problems in a JsonNode or its descendents.
+ *
+ * If a problem is detected, return false, writing a description of the problem
+ * to errmsg (unless errmsg is NULL).
+ */
+bool json_check(const JsonNode *node, char errmsg[256]);
+
+// Added by Lea Anthony 28/11/2020
+int json_array_length(JsonNode *array);
+
+#endif
\ No newline at end of file
diff --git a/v2/internal/ffenestri/menu_darwin.c b/v2/internal/ffenestri/menu_darwin.c
new file mode 100644
index 000000000..282d3331e
--- /dev/null
+++ b/v2/internal/ffenestri/menu_darwin.c
@@ -0,0 +1,1001 @@
+//
+// Created by Lea Anthony on 6/1/21.
+//
+
+#include "ffenestri_darwin.h"
+#include "menu_darwin.h"
+#include "contextmenus_darwin.h"
+#include "common.h"
+
+// NewMenu creates a new Menu struct, saving the given menu structure as JSON
+Menu* NewMenu(JsonNode *menuData) {
+
+ Menu *result = malloc(sizeof(Menu));
+
+ result->processedMenu = menuData;
+
+ // No title by default
+ result->title = "";
+
+ // Initialise menuCallbackDataCache
+ vec_init(&result->callbackDataCache);
+
+ // Allocate MenuItem Map
+ if( 0 != hashmap_create((const unsigned)16, &result->menuItemMap)) {
+ ABORT("[NewMenu] Not enough memory to allocate menuItemMap!");
+ }
+ // Allocate the Radio Group Map
+ if( 0 != hashmap_create((const unsigned)4, &result->radioGroupMap)) {
+ ABORT("[NewMenu] Not enough memory to allocate radioGroupMap!");
+ }
+
+ // Init other members
+ result->menu = NULL;
+ result->parentData = NULL;
+
+ return result;
+}
+
+Menu* NewApplicationMenu(const char *menuAsJSON) {
+
+ // Parse the menu json
+ JsonNode *processedMenu = json_decode(menuAsJSON);
+ if( processedMenu == NULL ) {
+ // Parse error!
+ ABORT("Unable to parse Menu JSON: %s", menuAsJSON);
+ }
+
+ Menu *result = NewMenu(processedMenu);
+ result->menuType = ApplicationMenuType;
+ return result;
+}
+
+MenuItemCallbackData* CreateMenuItemCallbackData(Menu *menu, id menuItem, const char *menuID, enum MenuItemType menuItemType) {
+ MenuItemCallbackData* result = malloc(sizeof(MenuItemCallbackData));
+
+ result->menu = menu;
+ result->menuID = menuID;
+ result->menuItem = menuItem;
+ result->menuItemType = menuItemType;
+
+ // Store reference to this so we can destroy later
+ vec_push(&menu->callbackDataCache, result);
+
+ return result;
+}
+
+void DeleteMenu(Menu *menu) {
+
+ // Free menu item hashmap
+ hashmap_destroy(&menu->menuItemMap);
+
+ // Free radio group members
+ if( hashmap_num_entries(&menu->radioGroupMap) > 0 ) {
+ if (0 != hashmap_iterate_pairs(&menu->radioGroupMap, freeHashmapItem, NULL)) {
+ ABORT("[DeleteMenu] Failed to release radioGroupMap entries!");
+ }
+ }
+
+ // Free radio groups hashmap
+ hashmap_destroy(&menu->radioGroupMap);
+
+ // Free up the processed menu memory
+ if (menu->processedMenu != NULL) {
+ json_delete(menu->processedMenu);
+ menu->processedMenu = NULL;
+ }
+
+ // Release the callback data memory + vector
+ int i; MenuItemCallbackData* callbackData;
+ vec_foreach(&menu->callbackDataCache, callbackData, i) {
+ free(callbackData);
+ }
+ vec_deinit(&menu->callbackDataCache);
+
+ free(menu);
+}
+
+// Creates a JSON message for the given menuItemID and data
+const char* createMenuClickedMessage(const char *menuItemID, const char *data, enum MenuType menuType, const char *parentID) {
+
+ JsonNode *jsonObject = json_mkobject();
+ if (menuItemID == NULL ) {
+ ABORT("Item ID NULL for menu!!\n");
+ }
+ json_append_member(jsonObject, "menuItemID", json_mkstring(menuItemID));
+ json_append_member(jsonObject, "menuType", json_mkstring(MenuTypeAsString[(int)menuType]));
+ if (data != NULL) {
+ json_append_member(jsonObject, "data", json_mkstring(data));
+ }
+ if (parentID != NULL) {
+ json_append_member(jsonObject, "parentID", json_mkstring(parentID));
+ }
+ const char *payload = json_encode(jsonObject);
+ json_delete(jsonObject);
+ const char *result = concat("MC", payload);
+ MEMFREE(payload);
+ return result;
+}
+
+// Callback for text menu items
+void menuItemCallback(id self, SEL cmd, id sender) {
+ MenuItemCallbackData *callbackData = (MenuItemCallbackData *)msg_reg(msg_reg(sender, s("representedObject")), s("pointerValue"));
+ const char *message;
+
+ // Update checkbox / radio item
+ if( callbackData->menuItemType == Checkbox) {
+ // Toggle state
+ bool state = msg_reg(callbackData->menuItem, s("state"));
+ msg_int(callbackData->menuItem, s("setState:"), (state? NSControlStateValueOff : NSControlStateValueOn));
+ } else if( callbackData->menuItemType == Radio ) {
+ // Check the menu items' current state
+ bool selected = (bool)msg_reg(callbackData->menuItem, s("state"));
+
+ // If it's already selected, exit early
+ if (selected) return;
+
+ // Get this item's radio group members and turn them off
+ id *members = (id*)hashmap_get(&(callbackData->menu->radioGroupMap), (char*)callbackData->menuID, strlen(callbackData->menuID));
+
+ // Uncheck all members of the group
+ id thisMember = members[0];
+ int count = 0;
+ while(thisMember != NULL) {
+ msg_int(thisMember, s("setState:"), NSControlStateValueOff);
+ count = count + 1;
+ thisMember = members[count];
+ }
+
+ // check the selected menu item
+ msg_int(callbackData->menuItem, s("setState:"), NSControlStateValueOn);
+ }
+
+ const char *menuID = callbackData->menuID;
+ const char *data = NULL;
+ enum MenuType menuType = callbackData->menu->menuType;
+ const char *parentID = NULL;
+
+ // Generate message to send to backend
+ if( menuType == ContextMenuType ) {
+ // Get the context menu data from the menu
+ ContextMenu* contextMenu = (ContextMenu*) callbackData->menu->parentData;
+ data = contextMenu->contextMenuData;
+ parentID = contextMenu->ID;
+ } else if ( menuType == TrayMenuType ) {
+ parentID = (const char*) callbackData->menu->parentData;
+ }
+
+ message = createMenuClickedMessage(menuID, data, menuType, parentID);
+
+ // Notify the backend
+ messageFromWindowCallback(message);
+ MEMFREE(message);
+}
+
+id processAcceleratorKey(const char *key) {
+
+ // Guard against no accelerator key
+ if( key == NULL ) {
+ return str("");
+ }
+
+ if( STREQ(key, "backspace") ) {
+ return strunicode(0x0008);
+ }
+ if( STREQ(key, "tab") ) {
+ return strunicode(0x0009);
+ }
+ if( STREQ(key, "return") ) {
+ return strunicode(0x000d);
+ }
+ if( STREQ(key, "enter") ) {
+ return strunicode(0x000d);
+ }
+ if( STREQ(key, "escape") ) {
+ return strunicode(0x001b);
+ }
+ if( STREQ(key, "left") ) {
+ return strunicode(0x001c);
+ }
+ if( STREQ(key, "right") ) {
+ return strunicode(0x001d);
+ }
+ if( STREQ(key, "up") ) {
+ return strunicode(0x001e);
+ }
+ if( STREQ(key, "down") ) {
+ return strunicode(0x001f);
+ }
+ if( STREQ(key, "space") ) {
+ return strunicode(0x0020);
+ }
+ if( STREQ(key, "delete") ) {
+ return strunicode(0x007f);
+ }
+ if( STREQ(key, "home") ) {
+ return strunicode(0x2196);
+ }
+ if( STREQ(key, "end") ) {
+ return strunicode(0x2198);
+ }
+ if( STREQ(key, "page up") ) {
+ return strunicode(0x21de);
+ }
+ if( STREQ(key, "page down") ) {
+ return strunicode(0x21df);
+ }
+ if( STREQ(key, "f1") ) {
+ return strunicode(0xf704);
+ }
+ if( STREQ(key, "f2") ) {
+ return strunicode(0xf705);
+ }
+ if( STREQ(key, "f3") ) {
+ return strunicode(0xf706);
+ }
+ if( STREQ(key, "f4") ) {
+ return strunicode(0xf707);
+ }
+ if( STREQ(key, "f5") ) {
+ return strunicode(0xf708);
+ }
+ if( STREQ(key, "f6") ) {
+ return strunicode(0xf709);
+ }
+ if( STREQ(key, "f7") ) {
+ return strunicode(0xf70a);
+ }
+ if( STREQ(key, "f8") ) {
+ return strunicode(0xf70b);
+ }
+ if( STREQ(key, "f9") ) {
+ return strunicode(0xf70c);
+ }
+ if( STREQ(key, "f10") ) {
+ return strunicode(0xf70d);
+ }
+ if( STREQ(key, "f11") ) {
+ return strunicode(0xf70e);
+ }
+ if( STREQ(key, "f12") ) {
+ return strunicode(0xf70f);
+ }
+ if( STREQ(key, "f13") ) {
+ return strunicode(0xf710);
+ }
+ if( STREQ(key, "f14") ) {
+ return strunicode(0xf711);
+ }
+ if( STREQ(key, "f15") ) {
+ return strunicode(0xf712);
+ }
+ if( STREQ(key, "f16") ) {
+ return strunicode(0xf713);
+ }
+ if( STREQ(key, "f17") ) {
+ return strunicode(0xf714);
+ }
+ if( STREQ(key, "f18") ) {
+ return strunicode(0xf715);
+ }
+ if( STREQ(key, "f19") ) {
+ return strunicode(0xf716);
+ }
+ if( STREQ(key, "f20") ) {
+ return strunicode(0xf717);
+ }
+ if( STREQ(key, "f21") ) {
+ return strunicode(0xf718);
+ }
+ if( STREQ(key, "f22") ) {
+ return strunicode(0xf719);
+ }
+ if( STREQ(key, "f23") ) {
+ return strunicode(0xf71a);
+ }
+ if( STREQ(key, "f24") ) {
+ return strunicode(0xf71b);
+ }
+ if( STREQ(key, "f25") ) {
+ return strunicode(0xf71c);
+ }
+ if( STREQ(key, "f26") ) {
+ return strunicode(0xf71d);
+ }
+ if( STREQ(key, "f27") ) {
+ return strunicode(0xf71e);
+ }
+ if( STREQ(key, "f28") ) {
+ return strunicode(0xf71f);
+ }
+ if( STREQ(key, "f29") ) {
+ return strunicode(0xf720);
+ }
+ if( STREQ(key, "f30") ) {
+ return strunicode(0xf721);
+ }
+ if( STREQ(key, "f31") ) {
+ return strunicode(0xf722);
+ }
+ if( STREQ(key, "f32") ) {
+ return strunicode(0xf723);
+ }
+ if( STREQ(key, "f33") ) {
+ return strunicode(0xf724);
+ }
+ if( STREQ(key, "f34") ) {
+ return strunicode(0xf725);
+ }
+ if( STREQ(key, "f35") ) {
+ return strunicode(0xf726);
+ }
+// if( STREQ(key, "Insert") ) {
+// return strunicode(0xf727);
+// }
+// if( STREQ(key, "PrintScreen") ) {
+// return strunicode(0xf72e);
+// }
+// if( STREQ(key, "ScrollLock") ) {
+// return strunicode(0xf72f);
+// }
+ if( STREQ(key, "numLock") ) {
+ return strunicode(0xf739);
+ }
+
+ return str(key);
+}
+
+
+void addSeparator(id menu) {
+ id item = msg_reg(c("NSMenuItem"), s("separatorItem"));
+ msg_id(menu, s("addItem:"), item);
+}
+
+id createMenuItemNoAutorelease( id title, const char *action, const char *key) {
+ id item = ALLOC("NSMenuItem");
+ ((id(*)(id, SEL, id, SEL, id))objc_msgSend)(item, s("initWithTitle:action:keyEquivalent:"), title, s(action), str(key));
+ return item;
+}
+
+id createMenuItem(id title, const char *action, const char *key) {
+ id item = ALLOC("NSMenuItem");
+ ((id(*)(id, SEL, id, SEL, id))objc_msgSend)(item, s("initWithTitle:action:keyEquivalent:"), title, s(action), str(key));
+ msg_reg(item, s("autorelease"));
+ return item;
+}
+
+id addMenuItem(id menu, const char *title, const char *action, const char *key, bool disabled) {
+ id item = createMenuItem(str(title), action, key);
+ msg_bool(item, s("setEnabled:"), !disabled);
+ msg_id(menu, s("addItem:"), item);
+ return item;
+}
+
+id createMenu(id title) {
+ id menu = ALLOC("NSMenu");
+ msg_id(menu, s("initWithTitle:"), title);
+ msg_bool(menu, s("setAutoenablesItems:"), NO);
+ msg_reg(menu, s("autorelease"));
+ return menu;
+}
+
+void createDefaultAppMenu(id parentMenu) {
+// App Menu
+ id appName = msg_reg(msg_reg(c("NSProcessInfo"), s("processInfo")), s("processName"));
+ id appMenuItem = createMenuItemNoAutorelease(appName, NULL, "");
+ id appMenu = createMenu(appName);
+
+ msg_id(appMenuItem, s("setSubmenu:"), appMenu);
+ msg_id(parentMenu, s("addItem:"), appMenuItem);
+
+ id title = msg_id(str("Hide "), s("stringByAppendingString:"), appName);
+ id item = createMenuItem(title, "hide:", "h");
+ msg_id(appMenu, s("addItem:"), item);
+
+ id hideOthers = addMenuItem(appMenu, "Hide Others", "hideOtherApplications:", "h", FALSE);
+ msg_int(hideOthers, s("setKeyEquivalentModifierMask:"), (NSEventModifierFlagOption | NSEventModifierFlagCommand));
+
+ addMenuItem(appMenu, "Show All", "unhideAllApplications:", "", FALSE);
+
+ addSeparator(appMenu);
+
+ title = msg_id(str("Quit "), s("stringByAppendingString:"), appName);
+ item = createMenuItem(title, "terminate:", "q");
+ msg_id(appMenu, s("addItem:"), item);
+}
+
+void createDefaultEditMenu(id parentMenu) {
+ // Edit Menu
+ id editMenuItem = createMenuItemNoAutorelease(str("Edit"), NULL, "");
+ id editMenu = createMenu(str("Edit"));
+
+ msg_id(editMenuItem, s("setSubmenu:"), editMenu);
+ msg_id(parentMenu, s("addItem:"), editMenuItem);
+
+ addMenuItem(editMenu, "Undo", "undo:", "z", FALSE);
+ addMenuItem(editMenu, "Redo", "redo:", "y", FALSE);
+ addSeparator(editMenu);
+ addMenuItem(editMenu, "Cut", "cut:", "x", FALSE);
+ addMenuItem(editMenu, "Copy", "copy:", "c", FALSE);
+ addMenuItem(editMenu, "Paste", "paste:", "v", FALSE);
+ addMenuItem(editMenu, "Select All", "selectAll:", "a", FALSE);
+}
+
+void processMenuRole(Menu *menu, id parentMenu, JsonNode *item) {
+ const char *roleName = item->string_;
+
+ if ( STREQ(roleName, "appMenu") ) {
+ createDefaultAppMenu(parentMenu);
+ return;
+ }
+ if ( STREQ(roleName, "editMenu")) {
+ createDefaultEditMenu(parentMenu);
+ return;
+ }
+ if ( STREQ(roleName, "hide")) {
+ addMenuItem(parentMenu, "Hide Window", "hide:", "h", FALSE);
+ return;
+ }
+ if ( STREQ(roleName, "hideothers")) {
+ id hideOthers = addMenuItem(parentMenu, "Hide Others", "hideOtherApplications:", "h", FALSE);
+ msg_int(hideOthers, s("setKeyEquivalentModifierMask:"), (NSEventModifierFlagOption | NSEventModifierFlagCommand));
+ return;
+ }
+ if ( STREQ(roleName, "unhide")) {
+ addMenuItem(parentMenu, "Show All", "unhideAllApplications:", "", FALSE);
+ return;
+ }
+ if ( STREQ(roleName, "front")) {
+ addMenuItem(parentMenu, "Bring All to Front", "arrangeInFront:", "", FALSE);
+ return;
+ }
+ if ( STREQ(roleName, "undo")) {
+ addMenuItem(parentMenu, "Undo", "undo:", "z", FALSE);
+ return;
+ }
+ if ( STREQ(roleName, "redo")) {
+ addMenuItem(parentMenu, "Redo", "redo:", "y", FALSE);
+ return;
+ }
+ if ( STREQ(roleName, "cut")) {
+ addMenuItem(parentMenu, "Cut", "cut:", "x", FALSE);
+ return;
+ }
+ if ( STREQ(roleName, "copy")) {
+ addMenuItem(parentMenu, "Copy", "copy:", "c", FALSE);
+ return;
+ }
+ if ( STREQ(roleName, "paste")) {
+ addMenuItem(parentMenu, "Paste", "paste:", "v", FALSE);
+ return;
+ }
+ if ( STREQ(roleName, "delete")) {
+ addMenuItem(parentMenu, "Delete", "delete:", "", FALSE);
+ return;
+ }
+ if( STREQ(roleName, "pasteandmatchstyle")) {
+ id pasteandmatchstyle = addMenuItem(parentMenu, "Paste and Match Style", "pasteandmatchstyle:", "v", FALSE);
+ msg_int(pasteandmatchstyle, s("setKeyEquivalentModifierMask:"), (NSEventModifierFlagOption | NSEventModifierFlagShift | NSEventModifierFlagCommand));
+ }
+ if ( STREQ(roleName, "selectall")) {
+ addMenuItem(parentMenu, "Select All", "selectAll:", "a", FALSE);
+ return;
+ }
+ if ( STREQ(roleName, "minimize")) {
+ addMenuItem(parentMenu, "Minimize", "miniaturize:", "m", FALSE);
+ return;
+ }
+ if ( STREQ(roleName, "zoom")) {
+ addMenuItem(parentMenu, "Zoom", "performZoom:", "", FALSE);
+ return;
+ }
+ if ( STREQ(roleName, "quit")) {
+ addMenuItem(parentMenu, "Quit (More work TBD)", "terminate:", "q", FALSE);
+ return;
+ }
+ if ( STREQ(roleName, "togglefullscreen")) {
+ addMenuItem(parentMenu, "Toggle Full Screen", "toggleFullScreen:", "f", FALSE);
+ return;
+ }
+
+}
+
+// This converts a string array of modifiers into the
+// equivalent MacOS Modifier Flags
+unsigned long parseModifiers(const char **modifiers) {
+
+ // Our result is a modifier flag list
+ unsigned long result = 0;
+
+ const char *thisModifier = modifiers[0];
+ int count = 0;
+ while( thisModifier != NULL ) {
+
+ // Determine flags
+ if( STREQ(thisModifier, "cmdorctrl") ) {
+ result |= NSEventModifierFlagCommand;
+ }
+ if( STREQ(thisModifier, "optionoralt") ) {
+ result |= NSEventModifierFlagOption;
+ }
+ if( STREQ(thisModifier, "shift") ) {
+ result |= NSEventModifierFlagShift;
+ }
+ if( STREQ(thisModifier, "super") ) {
+ result |= NSEventModifierFlagCommand;
+ }
+ if( STREQ(thisModifier, "ctrl") ) {
+ result |= NSEventModifierFlagControl;
+ }
+ count++;
+ thisModifier = modifiers[count];
+ }
+ return result;
+}
+
+id processRadioMenuItem(Menu *menu, id parentmenu, const char *title, const char *menuid, bool disabled, bool checked, const char *acceleratorkey) {
+ id item = ALLOC("NSMenuItem");
+
+ // Store the item in the menu item map
+ hashmap_put(&menu->menuItemMap, (char*)menuid, strlen(menuid), item);
+
+ // Create a MenuItemCallbackData
+ MenuItemCallbackData *callback = CreateMenuItemCallbackData(menu, item, menuid, Radio);
+
+ id wrappedId = msg_id(c("NSValue"), s("valueWithPointer:"), (id)callback);
+ msg_id(item, s("setRepresentedObject:"), wrappedId);
+
+ id key = processAcceleratorKey(acceleratorkey);
+
+ ((id(*)(id, SEL, id, SEL, id))objc_msgSend)(item, s("initWithTitle:action:keyEquivalent:"), str(title), s("menuItemCallback:"), key);
+
+ msg_bool(item, s("setEnabled:"), !disabled);
+ msg_reg(item, s("autorelease"));
+ msg_int(item, s("setState:"), (checked ? NSControlStateValueOn : NSControlStateValueOff));
+
+ msg_id(parentmenu, s("addItem:"), item);
+ return item;
+
+}
+
+id processCheckboxMenuItem(Menu *menu, id parentmenu, const char *title, const char *menuid, bool disabled, bool checked, const char *key) {
+
+ id item = ALLOC("NSMenuItem");
+ msg_reg(item, s("autorelease"));
+
+ // Store the item in the menu item map
+ hashmap_put(&menu->menuItemMap, (char*)menuid, strlen(menuid), item);
+
+ // Create a MenuItemCallbackData
+ MenuItemCallbackData *callback = CreateMenuItemCallbackData(menu, item, menuid, Checkbox);
+
+ id wrappedId = msg_id(c("NSValue"), s("valueWithPointer:"), (id)callback);
+ msg_id(item, s("setRepresentedObject:"), wrappedId);
+ ((id(*)(id, SEL, id, SEL, id))objc_msgSend)(item, s("initWithTitle:action:keyEquivalent:"), str(title), s("menuItemCallback:"), str(key));
+ msg_bool(item, s("setEnabled:"), !disabled);
+ msg_int(item, s("setState:"), (checked ? NSControlStateValueOn : NSControlStateValueOff));
+ msg_id(parentmenu, s("addItem:"), item);
+ return item;
+}
+
+// getColour returns the colour from a styledLabel based on the key
+const char* getColour(JsonNode *styledLabelEntry, const char* key) {
+ JsonNode* colEntry = getJSONObject(styledLabelEntry, key);
+ if( colEntry == NULL ) {
+ return NULL;
+ }
+ return getJSONString(colEntry, "hex");
+}
+
+id createAttributedStringFromStyledLabel(JsonNode *styledLabel, const char* fontName, int fontSize) {
+
+ // Create result
+ id attributedString = ALLOC_INIT("NSMutableAttributedString");
+ msg_reg(attributedString, s("autorelease"));
+
+ // Create new Dictionary
+ id dictionary = ALLOC_INIT("NSMutableDictionary");
+ msg_reg(dictionary, s("autorelease"));
+
+ // Use default font
+ CGFloat fontSizeFloat = (CGFloat)fontSize;
+ id font = ((id(*)(id, SEL, CGFloat))objc_msgSend)(c("NSFont"), s("menuBarFontOfSize:"), fontSizeFloat);
+
+ // Check user supplied font
+ if( STR_HAS_CHARS(fontName) ) {
+ id fontNameAsNSString = str(fontName);
+ id userFont = ((id(*)(id, SEL, id, CGFloat))objc_msgSend)(c("NSFont"), s("fontWithName:size:"), fontNameAsNSString, fontSizeFloat);
+ if( userFont != NULL ) {
+ font = userFont;
+ }
+ }
+
+ id fan = lookupStringConstant(str("NSFontAttributeName"));
+ id NSForegroundColorAttributeName = lookupStringConstant(str("NSForegroundColorAttributeName"));
+ id NSBackgroundColorAttributeName = lookupStringConstant(str("NSBackgroundColorAttributeName"));
+
+ // Loop over styled text creating NSAttributedText and appending to result
+ JsonNode *styledLabelEntry;
+ json_foreach(styledLabelEntry, styledLabel) {
+
+ // Clear dictionary
+ msg_reg(dictionary, s("removeAllObjects"));
+
+ // Add font to dictionary
+ msg_id_id(dictionary, s("setObject:forKey:"), font, fan);
+
+ // Get Text
+ const char* thisLabel = mustJSONString(styledLabelEntry, "Label");
+
+ // Get foreground colour
+ const char *hexColour = getColour(styledLabelEntry, "FgCol");
+ if( hexColour != NULL) {
+ unsigned short r, g, b, a;
+
+ // white by default
+ r = g = b = a = 255;
+ int count = sscanf(hexColour, "#%02hx%02hx%02hx%02hx", &r, &g, &b, &a);
+ if (count > 0) {
+ id colour = ((id(*)(id, SEL, CGFloat, CGFloat, CGFloat, CGFloat))objc_msgSend)(c("NSColor"), s("colorWithCalibratedRed:green:blue:alpha:"),
+ (CGFloat)r / (CGFloat)255.0,
+ (CGFloat)g / (CGFloat)255.0,
+ (CGFloat)b / (CGFloat)255.0,
+ (CGFloat)a / (CGFloat)255.0);
+ msg_id_id(dictionary, s("setObject:forKey:"), colour, NSForegroundColorAttributeName);
+ }
+ }
+
+ // Get background colour
+ hexColour = getColour(styledLabelEntry, "BgCol");
+ if( hexColour != NULL) {
+ unsigned short r, g, b, a;
+
+ // white by default
+ r = g = b = a = 255;
+ int count = sscanf(hexColour, "#%02hx%02hx%02hx%02hx", &r, &g, &b, &a);
+ if (count > 0) {
+ id colour = ((id(*)(id, SEL, CGFloat, CGFloat, CGFloat, CGFloat))objc_msgSend)(c("NSColor"), s("colorWithCalibratedRed:green:blue:alpha:"),
+ (CGFloat)r / (CGFloat)255.0,
+ (CGFloat)g / (CGFloat)255.0,
+ (CGFloat)b / (CGFloat)255.0,
+ (CGFloat)a / (CGFloat)255.0);
+ msg_id_id(dictionary, s("setObject:forKey:"), colour, NSForegroundColorAttributeName);
+ }
+ }
+
+ // Create AttributedText
+ id thisString = ALLOC("NSMutableAttributedString");
+ msg_reg(thisString, s("autorelease"));
+ msg_id_id(thisString, s("initWithString:attributes:"), str(thisLabel), dictionary);
+
+ // Append text to result
+ msg_id(attributedString, s("appendAttributedString:"), thisString);
+ }
+
+ return attributedString;
+
+}
+
+
+id createAttributedString(const char* title, const char* fontName, int fontSize, const char* RGBA) {
+
+ // Create new Dictionary
+ id dictionary = ALLOC_INIT("NSMutableDictionary");
+ CGFloat fontSizeFloat = (CGFloat)fontSize;
+
+ // Use default font
+ id font = ((id(*)(id, SEL, CGFloat))objc_msgSend)(c("NSFont"), s("menuBarFontOfSize:"), fontSizeFloat);
+
+ // Check user supplied font
+ if( STR_HAS_CHARS(fontName) ) {
+ id fontNameAsNSString = str(fontName);
+ id userFont = ((id(*)(id, SEL, id, CGFloat))objc_msgSend)(c("NSFont"), s("fontWithName:size:"), fontNameAsNSString, fontSizeFloat);
+ if( userFont != NULL ) {
+ font = userFont;
+ }
+ }
+
+ // Add font to dictionary
+ id fan = lookupStringConstant(str("NSFontAttributeName"));
+ msg_id_id(dictionary, s("setObject:forKey:"), font, fan);
+
+ // RGBA
+ if( RGBA != NULL && strlen(RGBA) > 0) {
+ unsigned short r, g, b, a;
+
+ // white by default
+ r = g = b = a = 255;
+ int count = sscanf(RGBA, "#%02hx%02hx%02hx%02hx", &r, &g, &b, &a);
+ if (count > 0) {
+ id colour = ((id(*)(id, SEL, CGFloat, CGFloat, CGFloat, CGFloat))objc_msgSend)(c("NSColor"), s("colorWithCalibratedRed:green:blue:alpha:"),
+ (CGFloat)r / (CGFloat)255.0,
+ (CGFloat)g / (CGFloat)255.0,
+ (CGFloat)b / (CGFloat)255.0,
+ (CGFloat)a / (CGFloat)255.0);
+ id NSForegroundColorAttributeName = lookupStringConstant(str("NSForegroundColorAttributeName"));
+ msg_id_id(dictionary, s("setObject:forKey:"), colour, NSForegroundColorAttributeName);
+ }
+ }
+
+ id attributedString = ALLOC("NSMutableAttributedString");
+ msg_id_id(attributedString, s("initWithString:attributes:"), str(title), dictionary);
+ msg_reg(attributedString, s("autorelease"));
+ msg_reg(dictionary, s("autorelease"));
+ return attributedString;
+}
+
+id processTextMenuItem(Menu *menu, id parentMenu, const char *title, const char *menuid, bool disabled, const char *acceleratorkey, const char **modifiers, const char* tooltip, const char* image, const char* fontName, int fontSize, const char* RGBA, bool templateImage, bool alternate, JsonNode* styledLabel) {
+ id item = ALLOC("NSMenuItem");
+ msg_reg(item, s("autorelease"));
+
+ // Create a MenuItemCallbackData
+ MenuItemCallbackData *callback = CreateMenuItemCallbackData(menu, item, menuid, Text);
+
+ id wrappedId = msg_id(c("NSValue"), s("valueWithPointer:"), (id)callback);
+ msg_id(item, s("setRepresentedObject:"), wrappedId);
+
+ if( !alternate ) {
+ id key = processAcceleratorKey(acceleratorkey);
+ ((id(*)(id, SEL, id, SEL, id))objc_msgSend)(item, s("initWithTitle:action:keyEquivalent:"), str(title),
+ s("menuItemCallback:"), key);
+ } else {
+ ((id(*)(id, SEL, id, SEL, id))objc_msgSend)(item, s("initWithTitle:action:keyEquivalent:"), str(title), s("menuItemCallback:"), str(""));
+ }
+
+ if( tooltip != NULL ) {
+ msg_id(item, s("setToolTip:"), str(tooltip));
+ }
+
+ // Process image
+ if( image != NULL && strlen(image) > 0) {
+ id nsimage = createImageFromBase64Data(image, templateImage);
+ msg_id(item, s("setImage:"), nsimage);
+ }
+
+ id attributedString = NULL;
+ if( styledLabel != NULL) {
+ attributedString = createAttributedStringFromStyledLabel(styledLabel, fontName, fontSize);
+ } else {
+ attributedString = createAttributedString(title, fontName, fontSize, RGBA);
+ }
+ msg_id(item, s("setAttributedTitle:"), attributedString);
+
+//msg_id(item, s("setTitle:"), str(title));
+
+ msg_bool(item, s("setEnabled:"), !disabled);
+
+ // Process modifiers
+ if( modifiers != NULL && !alternate) {
+ unsigned long modifierFlags = parseModifiers(modifiers);
+ ((id(*)(id, SEL, unsigned long))objc_msgSend)(item, s("setKeyEquivalentModifierMask:"), modifierFlags);
+ }
+
+ // alternate
+ if( alternate ) {
+ msg_bool(item, s("setAlternate:"), true);
+ msg_int(item, s("setKeyEquivalentModifierMask:"), NSEventModifierFlagOption);
+ }
+ msg_id(parentMenu, s("addItem:"), item);
+
+ return item;
+}
+
+void processMenuItem(Menu *menu, id parentMenu, JsonNode *item) {
+
+ // Check if this item is hidden and if so, exit early!
+ bool hidden = false;
+ getJSONBool(item, "Hidden", &hidden);
+ if( hidden ) {
+ return;
+ }
+
+ // Get the role
+ JsonNode *role = json_find_member(item, "Role");
+ if( role != NULL ) {
+ processMenuRole(menu, parentMenu, role);
+ return;
+ }
+
+ // This is a user menu. Get the common data
+ // Get the label
+ const char *label = getJSONString(item, "Label");
+ if ( label == NULL) {
+ label = "(empty)";
+ }
+
+ // Check for a styled label
+ JsonNode *styledLabel = getJSONObject(item, "StyledLabel");
+
+ // Is this an alternate menu item?
+ bool alternate = false;
+ getJSONBool(item, "MacAlternate", &alternate);
+
+ const char *menuid = getJSONString(item, "ID");
+ if ( menuid == NULL) {
+ menuid = "";
+ }
+
+ bool disabled = false;
+ getJSONBool(item, "Disabled", &disabled);
+
+ // Get the Accelerator
+ JsonNode *accelerator = json_find_member(item, "Accelerator");
+ const char *acceleratorkey = NULL;
+ const char **modifiers = NULL;
+
+ const char *tooltip = getJSONString(item, "Tooltip");
+ const char *image = getJSONString(item, "Image");
+ const char *fontName = getJSONString(item, "FontName");
+ const char *RGBA = getJSONString(item, "RGBA");
+ bool templateImage = false;
+ getJSONBool(item, "MacTemplateImage", &templateImage);
+
+ int fontSize = 0;
+ getJSONInt(item, "FontSize", &fontSize);
+
+ // If we have an accelerator
+ if( accelerator != NULL ) {
+ // Get the key
+ acceleratorkey = getJSONString(accelerator, "Key");
+ // Check if there are modifiers
+ JsonNode *modifiersList = json_find_member(accelerator, "Modifiers");
+ if ( modifiersList != NULL ) {
+ // Allocate an array of strings
+ int noOfModifiers = json_array_length(modifiersList);
+
+ // Do we have any?
+ if (noOfModifiers > 0) {
+ modifiers = malloc(sizeof(const char *) * (noOfModifiers + 1));
+ JsonNode *modifier;
+ int count = 0;
+ // Iterate the modifiers and save a reference to them in our new array
+ json_foreach(modifier, modifiersList) {
+ // Get modifier name
+ modifiers[count] = modifier->string_;
+ count++;
+ }
+ // Null terminate the modifier list
+ modifiers[count] = NULL;
+ }
+ }
+ }
+
+ // Get the Type
+ JsonNode *type = json_find_member(item, "Type");
+ if( type != NULL ) {
+ if( STREQ(type->string_, "Text") || STREQ(type->string_, "Submenu")) {
+ id thisMenuItem = processTextMenuItem(menu, parentMenu, label, menuid, disabled, acceleratorkey, modifiers, tooltip, image, fontName, fontSize, RGBA, templateImage, alternate, styledLabel);
+
+ // Check if this node has a submenu
+ JsonNode *submenu = json_find_member(item, "SubMenu");
+ if( submenu != NULL ) {
+ // Get the label
+ JsonNode *menuNameNode = json_find_member(item, "Label");
+ const char *name = "";
+ if ( menuNameNode != NULL) {
+ name = menuNameNode->string_;
+ }
+
+ id thisMenu = createMenu(str(name));
+
+ msg_id(thisMenuItem, s("setSubmenu:"), thisMenu);
+
+ JsonNode *submenuItems = json_find_member(submenu, "Items");
+ // If we have no items, just return
+ if ( submenuItems == NULL ) {
+ return;
+ }
+
+ // Loop over submenu items
+ JsonNode *item;
+ json_foreach(item, submenuItems) {
+ // Get item label
+ processMenuItem(menu, thisMenu, item);
+ }
+ }
+ }
+ else if ( STREQ(type->string_, "Separator")) {
+ addSeparator(parentMenu);
+ }
+ else if ( STREQ(type->string_, "Checkbox")) {
+ // Get checked state
+ bool checked = false;
+ getJSONBool(item, "Checked", &checked);
+
+ processCheckboxMenuItem(menu, parentMenu, label, menuid, disabled, checked, "");
+ }
+ else if ( STREQ(type->string_, "Radio")) {
+ // Get checked state
+ bool checked = false;
+ getJSONBool(item, "Checked", &checked);
+
+ processRadioMenuItem(menu, parentMenu, label, menuid, disabled, checked, "");
+ }
+ }
+
+ if ( modifiers != NULL ) {
+ free(modifiers);
+ }
+
+ return;
+}
+
+void processMenuData(Menu *menu, JsonNode *menuData) {
+ JsonNode *items = json_find_member(menuData, "Items");
+ if( items == NULL ) {
+ // Parse error!
+ ABORT("Unable to find 'Items' in menu JSON!");
+ }
+
+ // Iterate items
+ JsonNode *item;
+ json_foreach(item, items) {
+ // Process each menu item
+ processMenuItem(menu, menu->menu, item);
+ }
+}
+
+void processRadioGroupJSON(Menu *menu, JsonNode *radioGroup) {
+
+ int groupLength;
+ getJSONInt(radioGroup, "Length", &groupLength);
+ JsonNode *members = json_find_member(radioGroup, "Members");
+ JsonNode *member;
+
+ // Allocate array
+ size_t arrayLength = sizeof(id)*(groupLength+1);
+ id memberList[arrayLength];
+
+ // Build the radio group items
+ int count=0;
+ json_foreach(member, members) {
+ // Get menu by id
+ id menuItem = (id)hashmap_get(&menu->menuItemMap, (char*)member->string_, strlen(member->string_));
+ // Save Member
+ memberList[count] = menuItem;
+ count = count + 1;
+ }
+ // Null terminate array
+ memberList[groupLength] = 0;
+
+ // Store the members
+ json_foreach(member, members) {
+ // Copy the memberList
+ char *newMemberList = (char *)malloc(arrayLength);
+ memcpy(newMemberList, memberList, arrayLength);
+ // add group to each member of group
+ hashmap_put(&menu->radioGroupMap, member->string_, strlen(member->string_), newMemberList);
+ }
+
+}
+
+id GetMenu(Menu *menu) {
+
+ // Pull out the menu data
+ JsonNode *menuData = json_find_member(menu->processedMenu, "Menu");
+ if( menuData == NULL ) {
+ ABORT("Unable to find Menu data: %s", menu->processedMenu);
+ }
+
+ menu->menu = createMenu(str(""));
+
+ // Process the menu data
+ processMenuData(menu, menuData);
+
+ // Create the radiogroup cache
+ JsonNode *radioGroups = json_find_member(menu->processedMenu, "RadioGroups");
+ if( radioGroups == NULL ) {
+ // Parse error!
+ ABORT("Unable to find RadioGroups data: %s", menu->processedMenu);
+ }
+
+ // Iterate radio groups
+ JsonNode *radioGroup;
+ json_foreach(radioGroup, radioGroups) {
+ // Get item label
+ processRadioGroupJSON(menu, radioGroup);
+ }
+
+ return menu->menu;
+}
+
diff --git a/v2/internal/ffenestri/menu_darwin.h b/v2/internal/ffenestri/menu_darwin.h
new file mode 100644
index 000000000..a68c483bd
--- /dev/null
+++ b/v2/internal/ffenestri/menu_darwin.h
@@ -0,0 +1,117 @@
+//
+// Created by Lea Anthony on 6/1/21.
+//
+
+#ifndef MENU_DARWIN_H
+#define MENU_DARWIN_H
+
+#include "common.h"
+#include "ffenestri_darwin.h"
+
+enum MenuItemType {Text = 0, Checkbox = 1, Radio = 2};
+enum MenuType {ApplicationMenuType = 0, ContextMenuType = 1, TrayMenuType = 2};
+static const char *MenuTypeAsString[] = {
+ "ApplicationMenu", "ContextMenu", "TrayMenu",
+};
+
+typedef struct _NSRange {
+ unsigned long location;
+ unsigned long length;
+} NSRange;
+
+#define NSFontWeightUltraLight -0.8
+#define NSFontWeightThin -0.6
+#define NSFontWeightLight -0.4
+#define NSFontWeightRegular 0.0
+#define NSFontWeightMedium 0.23
+#define NSFontWeightSemibold 0.3
+#define NSFontWeightBold 0.4
+#define NSFontWeightHeavy 0.56
+#define NSFontWeightBlack 0.62
+
+extern void messageFromWindowCallback(const char *);
+
+typedef struct {
+
+ const char *title;
+
+ /*** Internal ***/
+
+ // The decoded version of the Menu JSON
+ JsonNode *processedMenu;
+
+ struct hashmap_s menuItemMap;
+ struct hashmap_s radioGroupMap;
+
+ // Vector to keep track of callback data memory
+ vec_void_t callbackDataCache;
+
+ // The NSMenu for this menu
+ id menu;
+
+ // The parent data, eg ContextMenuStore or Tray
+ void *parentData;
+
+ // The commands for the menu callbacks
+ const char *callbackCommand;
+
+ // This indicates if we are an Application Menu, tray menu or context menu
+ enum MenuType menuType;
+
+
+} Menu;
+
+
+typedef struct {
+ id menuItem;
+ Menu *menu;
+ const char *menuID;
+ enum MenuItemType menuItemType;
+} MenuItemCallbackData;
+
+
+
+// NewMenu creates a new Menu struct, saving the given menu structure as JSON
+Menu* NewMenu(JsonNode *menuData);
+
+Menu* NewApplicationMenu(const char *menuAsJSON);
+MenuItemCallbackData* CreateMenuItemCallbackData(Menu *menu, id menuItem, const char *menuID, enum MenuItemType menuItemType);
+
+void DeleteMenu(Menu *menu);
+
+// Creates a JSON message for the given menuItemID and data
+const char* createMenuClickedMessage(const char *menuItemID, const char *data, enum MenuType menuType, const char *parentID);
+// Callback for text menu items
+void menuItemCallback(id self, SEL cmd, id sender);
+id processAcceleratorKey(const char *key);
+
+
+void addSeparator(id menu);
+id createMenuItemNoAutorelease( id title, const char *action, const char *key);
+
+id createMenuItem(id title, const char *action, const char *key);
+
+id addMenuItem(id menu, const char *title, const char *action, const char *key, bool disabled);
+
+id createMenu(id title);
+void createDefaultAppMenu(id parentMenu);
+void createDefaultEditMenu(id parentMenu);
+
+void processMenuRole(Menu *menu, id parentMenu, JsonNode *item);
+// This converts a string array of modifiers into the
+// equivalent MacOS Modifier Flags
+unsigned long parseModifiers(const char **modifiers);
+id processRadioMenuItem(Menu *menu, id parentmenu, const char *title, const char *menuid, bool disabled, bool checked, const char *acceleratorkey);
+
+id processCheckboxMenuItem(Menu *menu, id parentmenu, const char *title, const char *menuid, bool disabled, bool checked, const char *key);
+
+id processTextMenuItem(Menu *menu, id parentMenu, const char *title, const char *menuid, bool disabled, const char *acceleratorkey, const char **modifiers, const char* tooltip, const char* image, const char* fontName, int fontSize, const char* RGBA, bool templateImage, bool alternate, JsonNode* styledLabel);
+void processMenuItem(Menu *menu, id parentMenu, JsonNode *item);
+void processMenuData(Menu *menu, JsonNode *menuData);
+
+void processRadioGroupJSON(Menu *menu, JsonNode *radioGroup);
+id GetMenu(Menu *menu);
+id createAttributedString(const char* title, const char* fontName, int fontSize, const char* RGBA);
+id createAttributedStringFromStyledLabel(JsonNode *styledLabel, const char* fontName, int fontSize);
+
+#endif //ASSETS_C_MENU_DARWIN_H
diff --git a/v2/internal/ffenestri/runtime_darwin.c b/v2/internal/ffenestri/runtime_darwin.c
new file mode 100644
index 000000000..0d733f87a
--- /dev/null
+++ b/v2/internal/ffenestri/runtime_darwin.c
@@ -0,0 +1,5 @@
+
+// runtime.c (c) 2019-Present Lea Anthony.
+// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
+// This file was auto-generated. DO NOT MODIFY.
+const unsigned char runtime[]={0x76, 0x61, 0x72, 0x20, 0x57, 0x61, 0x69, 0x6c, 0x73, 0x3d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6e, 0x29, 0x7b, 0x76, 0x61, 0x72, 0x20, 0x74, 0x3d, 0x7b, 0x7d, 0x3b, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x65, 0x28, 0x72, 0x29, 0x7b, 0x69, 0x66, 0x28, 0x74, 0x5b, 0x72, 0x5d, 0x29, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x74, 0x5b, 0x72, 0x5d, 0x2e, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x73, 0x3b, 0x76, 0x61, 0x72, 0x20, 0x69, 0x3d, 0x74, 0x5b, 0x72, 0x5d, 0x3d, 0x7b, 0x69, 0x3a, 0x72, 0x2c, 0x6c, 0x3a, 0x21, 0x31, 0x2c, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x73, 0x3a, 0x7b, 0x7d, 0x7d, 0x3b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6e, 0x5b, 0x72, 0x5d, 0x2e, 0x63, 0x61, 0x6c, 0x6c, 0x28, 0x69, 0x2e, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x73, 0x2c, 0x69, 0x2c, 0x69, 0x2e, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x73, 0x2c, 0x65, 0x29, 0x2c, 0x69, 0x2e, 0x6c, 0x3d, 0x21, 0x30, 0x2c, 0x69, 0x2e, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x73, 0x7d, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x65, 0x2e, 0x6d, 0x3d, 0x6e, 0x2c, 0x65, 0x2e, 0x63, 0x3d, 0x74, 0x2c, 0x65, 0x2e, 0x64, 0x3d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6e, 0x2c, 0x74, 0x2c, 0x72, 0x29, 0x7b, 0x65, 0x2e, 0x6f, 0x28, 0x6e, 0x2c, 0x74, 0x29, 0x7c, 0x7c, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x28, 0x6e, 0x2c, 0x74, 0x2c, 0x7b, 0x65, 0x6e, 0x75, 0x6d, 0x65, 0x72, 0x61, 0x62, 0x6c, 0x65, 0x3a, 0x21, 0x30, 0x2c, 0x67, 0x65, 0x74, 0x3a, 0x72, 0x7d, 0x29, 0x7d, 0x2c, 0x65, 0x2e, 0x72, 0x3d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6e, 0x29, 0x7b, 0x22, 0x75, 0x6e, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, 0x22, 0x21, 0x3d, 0x74, 0x79, 0x70, 0x65, 0x6f, 0x66, 0x20, 0x53, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x26, 0x26, 0x53, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x2e, 0x74, 0x6f, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x54, 0x61, 0x67, 0x26, 0x26, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x28, 0x6e, 0x2c, 0x53, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x2e, 0x74, 0x6f, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x54, 0x61, 0x67, 0x2c, 0x7b, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x22, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x22, 0x7d, 0x29, 0x2c, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x28, 0x6e, 0x2c, 0x22, 0x5f, 0x5f, 0x65, 0x73, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x22, 0x2c, 0x7b, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x21, 0x30, 0x7d, 0x29, 0x7d, 0x2c, 0x65, 0x2e, 0x74, 0x3d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6e, 0x2c, 0x74, 0x29, 0x7b, 0x69, 0x66, 0x28, 0x31, 0x26, 0x74, 0x26, 0x26, 0x28, 0x6e, 0x3d, 0x65, 0x28, 0x6e, 0x29, 0x29, 0x2c, 0x38, 0x26, 0x74, 0x29, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6e, 0x3b, 0x69, 0x66, 0x28, 0x34, 0x26, 0x74, 0x26, 0x26, 0x22, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x22, 0x3d, 0x3d, 0x74, 0x79, 0x70, 0x65, 0x6f, 0x66, 0x20, 0x6e, 0x26, 0x26, 0x6e, 0x26, 0x26, 0x6e, 0x2e, 0x5f, 0x5f, 0x65, 0x73, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x29, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6e, 0x3b, 0x76, 0x61, 0x72, 0x20, 0x72, 0x3d, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x28, 0x6e, 0x75, 0x6c, 0x6c, 0x29, 0x3b, 0x69, 0x66, 0x28, 0x65, 0x2e, 0x72, 0x28, 0x72, 0x29, 0x2c, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x28, 0x72, 0x2c, 0x22, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x22, 0x2c, 0x7b, 0x65, 0x6e, 0x75, 0x6d, 0x65, 0x72, 0x61, 0x62, 0x6c, 0x65, 0x3a, 0x21, 0x30, 0x2c, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x6e, 0x7d, 0x29, 0x2c, 0x32, 0x26, 0x74, 0x26, 0x26, 0x22, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x22, 0x21, 0x3d, 0x74, 0x79, 0x70, 0x65, 0x6f, 0x66, 0x20, 0x6e, 0x29, 0x66, 0x6f, 0x72, 0x28, 0x76, 0x61, 0x72, 0x20, 0x69, 0x20, 0x69, 0x6e, 0x20, 0x6e, 0x29, 0x65, 0x2e, 0x64, 0x28, 0x72, 0x2c, 0x69, 0x2c, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x74, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6e, 0x5b, 0x74, 0x5d, 0x7d, 0x2e, 0x62, 0x69, 0x6e, 0x64, 0x28, 0x6e, 0x75, 0x6c, 0x6c, 0x2c, 0x69, 0x29, 0x29, 0x3b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x72, 0x7d, 0x2c, 0x65, 0x2e, 0x6e, 0x3d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6e, 0x29, 0x7b, 0x76, 0x61, 0x72, 0x20, 0x74, 0x3d, 0x6e, 0x26, 0x26, 0x6e, 0x2e, 0x5f, 0x5f, 0x65, 0x73, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x3f, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6e, 0x2e, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x7d, 0x3a, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6e, 0x7d, 0x3b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x65, 0x2e, 0x64, 0x28, 0x74, 0x2c, 0x22, 0x61, 0x22, 0x2c, 0x74, 0x29, 0x2c, 0x74, 0x7d, 0x2c, 0x65, 0x2e, 0x6f, 0x3d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6e, 0x2c, 0x74, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x74, 0x79, 0x70, 0x65, 0x2e, 0x68, 0x61, 0x73, 0x4f, 0x77, 0x6e, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x2e, 0x63, 0x61, 0x6c, 0x6c, 0x28, 0x6e, 0x2c, 0x74, 0x29, 0x7d, 0x2c, 0x65, 0x2e, 0x70, 0x3d, 0x22, 0x22, 0x2c, 0x65, 0x28, 0x65, 0x2e, 0x73, 0x3d, 0x30, 0x29, 0x7d, 0x28, 0x5b, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6e, 0x2c, 0x74, 0x2c, 0x65, 0x29, 0x7b, 0x22, 0x75, 0x73, 0x65, 0x20, 0x73, 0x74, 0x72, 0x69, 0x63, 0x74, 0x22, 0x3b, 0x65, 0x2e, 0x72, 0x28, 0x74, 0x29, 0x3b, 0x76, 0x61, 0x72, 0x20, 0x72, 0x3d, 0x7b, 0x7d, 0x3b, 0x65, 0x2e, 0x72, 0x28, 0x72, 0x29, 0x2c, 0x65, 0x2e, 0x64, 0x28, 0x72, 0x2c, 0x22, 0x54, 0x72, 0x61, 0x63, 0x65, 0x22, 0x2c, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x76, 0x7d, 0x29, 0x29, 0x2c, 0x65, 0x2e, 0x64, 0x28, 0x72, 0x2c, 0x22, 0x50, 0x72, 0x69, 0x6e, 0x74, 0x22, 0x2c, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x70, 0x7d, 0x29, 0x29, 0x2c, 0x65, 0x2e, 0x64, 0x28, 0x72, 0x2c, 0x22, 0x44, 0x65, 0x62, 0x75, 0x67, 0x22, 0x2c, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x79, 0x7d, 0x29, 0x29, 0x2c, 0x65, 0x2e, 0x64, 0x28, 0x72, 0x2c, 0x22, 0x49, 0x6e, 0x66, 0x6f, 0x22, 0x2c, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6d, 0x7d, 0x29, 0x29, 0x2c, 0x65, 0x2e, 0x64, 0x28, 0x72, 0x2c, 0x22, 0x57, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x22, 0x2c, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x62, 0x7d, 0x29, 0x29, 0x2c, 0x65, 0x2e, 0x64, 0x28, 0x72, 0x2c, 0x22, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x2c, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x67, 0x7d, 0x29, 0x29, 0x2c, 0x65, 0x2e, 0x64, 0x28, 0x72, 0x2c, 0x22, 0x46, 0x61, 0x74, 0x61, 0x6c, 0x22, 0x2c, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x68, 0x7d, 0x29, 0x29, 0x2c, 0x65, 0x2e, 0x64, 0x28, 0x72, 0x2c, 0x22, 0x53, 0x65, 0x74, 0x4c, 0x6f, 0x67, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x22, 0x2c, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x53, 0x7d, 0x29, 0x29, 0x2c, 0x65, 0x2e, 0x64, 0x28, 0x72, 0x2c, 0x22, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x22, 0x2c, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x45, 0x7d, 0x29, 0x29, 0x3b, 0x76, 0x61, 0x72, 0x20, 0x69, 0x3d, 0x7b, 0x7d, 0x3b, 0x65, 0x2e, 0x72, 0x28, 0x69, 0x29, 0x2c, 0x65, 0x2e, 0x64, 0x28, 0x69, 0x2c, 0x22, 0x4f, 0x70, 0x65, 0x6e, 0x22, 0x2c, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x78, 0x7d, 0x29, 0x29, 0x3b, 0x76, 0x61, 0x72, 0x20, 0x6f, 0x3d, 0x7b, 0x7d, 0x3b, 0x65, 0x2e, 0x72, 0x28, 0x6f, 0x29, 0x2c, 0x65, 0x2e, 0x64, 0x28, 0x6f, 0x2c, 0x22, 0x43, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x22, 0x2c, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x4e, 0x7d, 0x29, 0x29, 0x2c, 0x65, 0x2e, 0x64, 0x28, 0x6f, 0x2c, 0x22, 0x53, 0x65, 0x74, 0x54, 0x69, 0x74, 0x6c, 0x65, 0x22, 0x2c, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x54, 0x7d, 0x29, 0x29, 0x2c, 0x65, 0x2e, 0x64, 0x28, 0x6f, 0x2c, 0x22, 0x46, 0x75, 0x6c, 0x6c, 0x73, 0x63, 0x72, 0x65, 0x65, 0x6e, 0x22, 0x2c, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6a, 0x7d, 0x29, 0x29, 0x2c, 0x65, 0x2e, 0x64, 0x28, 0x6f, 0x2c, 0x22, 0x55, 0x6e, 0x46, 0x75, 0x6c, 0x6c, 0x73, 0x63, 0x72, 0x65, 0x65, 0x6e, 0x22, 0x2c, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x44, 0x7d, 0x29, 0x29, 0x2c, 0x65, 0x2e, 0x64, 0x28, 0x6f, 0x2c, 0x22, 0x53, 0x65, 0x74, 0x53, 0x69, 0x7a, 0x65, 0x22, 0x2c, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x49, 0x7d, 0x29, 0x29, 0x2c, 0x65, 0x2e, 0x64, 0x28, 0x6f, 0x2c, 0x22, 0x53, 0x65, 0x74, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x2c, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x50, 0x7d, 0x29, 0x29, 0x2c, 0x65, 0x2e, 0x64, 0x28, 0x6f, 0x2c, 0x22, 0x48, 0x69, 0x64, 0x65, 0x22, 0x2c, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x41, 0x7d, 0x29, 0x29, 0x2c, 0x65, 0x2e, 0x64, 0x28, 0x6f, 0x2c, 0x22, 0x53, 0x68, 0x6f, 0x77, 0x22, 0x2c, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x4a, 0x7d, 0x29, 0x29, 0x2c, 0x65, 0x2e, 0x64, 0x28, 0x6f, 0x2c, 0x22, 0x4d, 0x61, 0x78, 0x69, 0x6d, 0x69, 0x73, 0x65, 0x22, 0x2c, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x4c, 0x7d, 0x29, 0x29, 0x2c, 0x65, 0x2e, 0x64, 0x28, 0x6f, 0x2c, 0x22, 0x55, 0x6e, 0x6d, 0x61, 0x78, 0x69, 0x6d, 0x69, 0x73, 0x65, 0x22, 0x2c, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x52, 0x7d, 0x29, 0x29, 0x2c, 0x65, 0x2e, 0x64, 0x28, 0x6f, 0x2c, 0x22, 0x4d, 0x69, 0x6e, 0x69, 0x6d, 0x69, 0x73, 0x65, 0x22, 0x2c, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x5f, 0x7d, 0x29, 0x29, 0x2c, 0x65, 0x2e, 0x64, 0x28, 0x6f, 0x2c, 0x22, 0x55, 0x6e, 0x6d, 0x69, 0x6e, 0x69, 0x6d, 0x69, 0x73, 0x65, 0x22, 0x2c, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x46, 0x7d, 0x29, 0x29, 0x2c, 0x65, 0x2e, 0x64, 0x28, 0x6f, 0x2c, 0x22, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x22, 0x2c, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x55, 0x7d, 0x29, 0x29, 0x3b, 0x76, 0x61, 0x72, 0x20, 0x61, 0x3d, 0x7b, 0x7d, 0x3b, 0x65, 0x2e, 0x72, 0x28, 0x61, 0x29, 0x2c, 0x65, 0x2e, 0x64, 0x28, 0x61, 0x2c, 0x22, 0x4f, 0x70, 0x65, 0x6e, 0x22, 0x2c, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x42, 0x7d, 0x29, 0x29, 0x2c, 0x65, 0x2e, 0x64, 0x28, 0x61, 0x2c, 0x22, 0x53, 0x61, 0x76, 0x65, 0x22, 0x2c, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x48, 0x7d, 0x29, 0x29, 0x2c, 0x65, 0x2e, 0x64, 0x28, 0x61, 0x2c, 0x22, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x2c, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x47, 0x7d, 0x29, 0x29, 0x3b, 0x76, 0x61, 0x72, 0x20, 0x75, 0x3d, 0x7b, 0x7d, 0x3b, 0x65, 0x2e, 0x72, 0x28, 0x75, 0x29, 0x2c, 0x65, 0x2e, 0x64, 0x28, 0x75, 0x2c, 0x22, 0x4e, 0x65, 0x77, 0x22, 0x2c, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x65, 0x6e, 0x7d, 0x29, 0x29, 0x3b, 0x76, 0x61, 0x72, 0x20, 0x63, 0x3d, 0x7b, 0x7d, 0x3b, 0x65, 0x2e, 0x72, 0x28, 0x63, 0x29, 0x2c, 0x65, 0x2e, 0x64, 0x28, 0x63, 0x2c, 0x22, 0x53, 0x65, 0x74, 0x49, 0x63, 0x6f, 0x6e, 0x22, 0x2c, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x72, 0x6e, 0x7d, 0x29, 0x29, 0x3b, 0x76, 0x61, 0x72, 0x20, 0x6c, 0x3d, 0x7b, 0x41, 0x70, 0x70, 0x54, 0x79, 0x70, 0x65, 0x3a, 0x22, 0x64, 0x65, 0x73, 0x6b, 0x74, 0x6f, 0x70, 0x22, 0x2c, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x3a, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x22, 0x64, 0x61, 0x72, 0x77, 0x69, 0x6e, 0x22, 0x7d, 0x7d, 0x3b, 0x76, 0x61, 0x72, 0x20, 0x73, 0x3d, 0x5b, 0x5d, 0x3b, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x66, 0x28, 0x6e, 0x29, 0x7b, 0x73, 0x2e, 0x70, 0x75, 0x73, 0x68, 0x28, 0x6e, 0x29, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x64, 0x28, 0x6e, 0x29, 0x7b, 0x69, 0x66, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6e, 0x29, 0x7b, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x77, 0x61, 0x69, 0x6c, 0x73, 0x49, 0x6e, 0x76, 0x6f, 0x6b, 0x65, 0x28, 0x6e, 0x29, 0x7d, 0x28, 0x6e, 0x29, 0x2c, 0x73, 0x2e, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x3e, 0x30, 0x29, 0x66, 0x6f, 0x72, 0x28, 0x76, 0x61, 0x72, 0x20, 0x74, 0x3d, 0x30, 0x3b, 0x74, 0x3c, 0x73, 0x2e, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x3b, 0x74, 0x2b, 0x2b, 0x29, 0x73, 0x5b, 0x74, 0x5d, 0x28, 0x6e, 0x29, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x77, 0x28, 0x6e, 0x2c, 0x74, 0x29, 0x7b, 0x64, 0x28, 0x22, 0x4c, 0x22, 0x2b, 0x6e, 0x2b, 0x74, 0x29, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x76, 0x28, 0x6e, 0x29, 0x7b, 0x77, 0x28, 0x22, 0x54, 0x22, 0x2c, 0x6e, 0x29, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x70, 0x28, 0x6e, 0x29, 0x7b, 0x77, 0x28, 0x22, 0x50, 0x22, 0x2c, 0x6e, 0x29, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x79, 0x28, 0x6e, 0x29, 0x7b, 0x77, 0x28, 0x22, 0x44, 0x22, 0x2c, 0x6e, 0x29, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6d, 0x28, 0x6e, 0x29, 0x7b, 0x77, 0x28, 0x22, 0x49, 0x22, 0x2c, 0x6e, 0x29, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x62, 0x28, 0x6e, 0x29, 0x7b, 0x77, 0x28, 0x22, 0x57, 0x22, 0x2c, 0x6e, 0x29, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x67, 0x28, 0x6e, 0x29, 0x7b, 0x77, 0x28, 0x22, 0x45, 0x22, 0x2c, 0x6e, 0x29, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x68, 0x28, 0x6e, 0x29, 0x7b, 0x77, 0x28, 0x22, 0x46, 0x22, 0x2c, 0x6e, 0x29, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x53, 0x28, 0x6e, 0x29, 0x7b, 0x77, 0x28, 0x22, 0x53, 0x22, 0x2c, 0x6e, 0x29, 0x7d, 0x76, 0x61, 0x72, 0x20, 0x4f, 0x2c, 0x45, 0x3d, 0x7b, 0x54, 0x52, 0x41, 0x43, 0x45, 0x3a, 0x31, 0x2c, 0x44, 0x45, 0x42, 0x55, 0x47, 0x3a, 0x32, 0x2c, 0x49, 0x4e, 0x46, 0x4f, 0x3a, 0x33, 0x2c, 0x57, 0x41, 0x52, 0x4e, 0x49, 0x4e, 0x47, 0x3a, 0x34, 0x2c, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x3a, 0x35, 0x7d, 0x2c, 0x6b, 0x3d, 0x7b, 0x7d, 0x3b, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x43, 0x28, 0x6e, 0x2c, 0x74, 0x2c, 0x65, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6e, 0x75, 0x6c, 0x6c, 0x21, 0x3d, 0x65, 0x26, 0x26, 0x6e, 0x75, 0x6c, 0x6c, 0x21, 0x3d, 0x65, 0x7c, 0x7c, 0x28, 0x65, 0x3d, 0x30, 0x29, 0x2c, 0x6e, 0x65, 0x77, 0x20, 0x50, 0x72, 0x6f, 0x6d, 0x69, 0x73, 0x65, 0x28, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x72, 0x2c, 0x69, 0x29, 0x7b, 0x76, 0x61, 0x72, 0x20, 0x6f, 0x3b, 0x64, 0x6f, 0x7b, 0x6f, 0x3d, 0x6e, 0x2b, 0x22, 0x2d, 0x22, 0x2b, 0x4f, 0x28, 0x29, 0x7d, 0x77, 0x68, 0x69, 0x6c, 0x65, 0x28, 0x6b, 0x5b, 0x6f, 0x5d, 0x29, 0x3b, 0x69, 0x66, 0x28, 0x65, 0x3e, 0x30, 0x29, 0x76, 0x61, 0x72, 0x20, 0x61, 0x3d, 0x73, 0x65, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x28, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x69, 0x28, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x28, 0x22, 0x43, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x6f, 0x20, 0x22, 0x2b, 0x6e, 0x2b, 0x22, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x64, 0x20, 0x6f, 0x75, 0x74, 0x2e, 0x20, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x20, 0x49, 0x44, 0x3a, 0x20, 0x22, 0x2b, 0x6f, 0x29, 0x29, 0x7d, 0x29, 0x2c, 0x65, 0x29, 0x3b, 0x6b, 0x5b, 0x6f, 0x5d, 0x3d, 0x7b, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x3a, 0x61, 0x2c, 0x72, 0x65, 0x6a, 0x65, 0x63, 0x74, 0x3a, 0x69, 0x2c, 0x72, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x3a, 0x72, 0x7d, 0x3b, 0x74, 0x72, 0x79, 0x7b, 0x76, 0x61, 0x72, 0x20, 0x75, 0x3d, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x3a, 0x6e, 0x2c, 0x61, 0x72, 0x67, 0x73, 0x3a, 0x74, 0x2c, 0x63, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x49, 0x44, 0x3a, 0x6f, 0x7d, 0x3b, 0x64, 0x28, 0x22, 0x43, 0x22, 0x2b, 0x4a, 0x53, 0x4f, 0x4e, 0x2e, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x69, 0x66, 0x79, 0x28, 0x75, 0x29, 0x29, 0x7d, 0x63, 0x61, 0x74, 0x63, 0x68, 0x28, 0x6e, 0x29, 0x7b, 0x63, 0x6f, 0x6e, 0x73, 0x6f, 0x6c, 0x65, 0x2e, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x28, 0x6e, 0x29, 0x7d, 0x7d, 0x29, 0x29, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x57, 0x28, 0x6e, 0x29, 0x7b, 0x76, 0x61, 0x72, 0x20, 0x74, 0x3b, 0x74, 0x72, 0x79, 0x7b, 0x74, 0x3d, 0x4a, 0x53, 0x4f, 0x4e, 0x2e, 0x70, 0x61, 0x72, 0x73, 0x65, 0x28, 0x6e, 0x29, 0x7d, 0x63, 0x61, 0x74, 0x63, 0x68, 0x28, 0x74, 0x29, 0x7b, 0x76, 0x61, 0x72, 0x20, 0x65, 0x3d, 0x22, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x20, 0x4a, 0x53, 0x4f, 0x4e, 0x20, 0x70, 0x61, 0x73, 0x73, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x3a, 0x20, 0x22, 0x2e, 0x63, 0x6f, 0x6e, 0x63, 0x61, 0x74, 0x28, 0x74, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2c, 0x22, 0x2e, 0x20, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x3a, 0x20, 0x22, 0x29, 0x2e, 0x63, 0x6f, 0x6e, 0x63, 0x61, 0x74, 0x28, 0x6e, 0x29, 0x3b, 0x74, 0x68, 0x72, 0x6f, 0x77, 0x20, 0x79, 0x28, 0x65, 0x29, 0x2c, 0x6e, 0x65, 0x77, 0x20, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x28, 0x65, 0x29, 0x7d, 0x76, 0x61, 0x72, 0x20, 0x72, 0x3d, 0x74, 0x2e, 0x63, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x69, 0x64, 0x2c, 0x69, 0x3d, 0x6b, 0x5b, 0x72, 0x5d, 0x3b, 0x69, 0x66, 0x28, 0x21, 0x69, 0x29, 0x7b, 0x76, 0x61, 0x72, 0x20, 0x6f, 0x3d, 0x22, 0x43, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x20, 0x27, 0x22, 0x2e, 0x63, 0x6f, 0x6e, 0x63, 0x61, 0x74, 0x28, 0x72, 0x2c, 0x22, 0x27, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x21, 0x21, 0x21, 0x22, 0x29, 0x3b, 0x74, 0x68, 0x72, 0x6f, 0x77, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x6f, 0x6c, 0x65, 0x2e, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x28, 0x6f, 0x29, 0x2c, 0x6e, 0x65, 0x77, 0x20, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x28, 0x6f, 0x29, 0x7d, 0x63, 0x6c, 0x65, 0x61, 0x72, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x28, 0x69, 0x2e, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x29, 0x2c, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x20, 0x6b, 0x5b, 0x72, 0x5d, 0x2c, 0x74, 0x2e, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x3f, 0x69, 0x2e, 0x72, 0x65, 0x6a, 0x65, 0x63, 0x74, 0x28, 0x74, 0x2e, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x29, 0x3a, 0x69, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x28, 0x74, 0x2e, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x29, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x4d, 0x28, 0x6e, 0x29, 0x7b, 0x76, 0x61, 0x72, 0x20, 0x74, 0x3d, 0x5b, 0x5d, 0x2e, 0x73, 0x6c, 0x69, 0x63, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x6c, 0x79, 0x28, 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x29, 0x2e, 0x73, 0x6c, 0x69, 0x63, 0x65, 0x28, 0x31, 0x29, 0x3b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x43, 0x28, 0x22, 0x2e, 0x77, 0x61, 0x69, 0x6c, 0x73, 0x2e, 0x22, 0x2b, 0x6e, 0x2c, 0x74, 0x29, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x78, 0x28, 0x6e, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x64, 0x28, 0x22, 0x52, 0x42, 0x4f, 0x22, 0x2b, 0x6e, 0x29, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x4e, 0x28, 0x29, 0x7b, 0x64, 0x28, 0x22, 0x57, 0x63, 0x22, 0x29, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x54, 0x28, 0x6e, 0x29, 0x7b, 0x64, 0x28, 0x22, 0x57, 0x54, 0x22, 0x2b, 0x6e, 0x29, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6a, 0x28, 0x29, 0x7b, 0x64, 0x28, 0x22, 0x57, 0x46, 0x22, 0x29, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x44, 0x28, 0x29, 0x7b, 0x64, 0x28, 0x22, 0x57, 0x66, 0x22, 0x29, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x49, 0x28, 0x6e, 0x2c, 0x74, 0x29, 0x7b, 0x64, 0x28, 0x22, 0x57, 0x73, 0x3a, 0x22, 0x2b, 0x6e, 0x2b, 0x22, 0x3a, 0x22, 0x2b, 0x74, 0x29, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x50, 0x28, 0x6e, 0x2c, 0x74, 0x29, 0x7b, 0x64, 0x28, 0x22, 0x57, 0x70, 0x3a, 0x22, 0x2b, 0x6e, 0x2b, 0x22, 0x3a, 0x22, 0x2b, 0x74, 0x29, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x28, 0x29, 0x7b, 0x64, 0x28, 0x22, 0x57, 0x48, 0x22, 0x29, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x4a, 0x28, 0x29, 0x7b, 0x64, 0x28, 0x22, 0x57, 0x53, 0x22, 0x29, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x4c, 0x28, 0x29, 0x7b, 0x64, 0x28, 0x22, 0x57, 0x4d, 0x22, 0x29, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x52, 0x28, 0x29, 0x7b, 0x64, 0x28, 0x22, 0x57, 0x55, 0x22, 0x29, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x5f, 0x28, 0x29, 0x7b, 0x64, 0x28, 0x22, 0x57, 0x6d, 0x22, 0x29, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x46, 0x28, 0x29, 0x7b, 0x64, 0x28, 0x22, 0x57, 0x75, 0x22, 0x29, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x55, 0x28, 0x29, 0x7b, 0x64, 0x28, 0x22, 0x57, 0x43, 0x22, 0x29, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x42, 0x28, 0x6e, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x4d, 0x28, 0x22, 0x44, 0x69, 0x61, 0x6c, 0x6f, 0x67, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x22, 0x2c, 0x6e, 0x29, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x48, 0x28, 0x6e, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x4d, 0x28, 0x22, 0x44, 0x69, 0x61, 0x6c, 0x6f, 0x67, 0x2e, 0x53, 0x61, 0x76, 0x65, 0x22, 0x2c, 0x6e, 0x29, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x47, 0x28, 0x6e, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x4d, 0x28, 0x22, 0x44, 0x69, 0x61, 0x6c, 0x6f, 0x67, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x2c, 0x6e, 0x29, 0x7d, 0x4f, 0x3d, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x3f, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x76, 0x61, 0x72, 0x20, 0x6e, 0x3d, 0x6e, 0x65, 0x77, 0x20, 0x55, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x41, 0x72, 0x72, 0x61, 0x79, 0x28, 0x31, 0x29, 0x3b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x67, 0x65, 0x74, 0x52, 0x61, 0x6e, 0x64, 0x6f, 0x6d, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x28, 0x6e, 0x29, 0x5b, 0x30, 0x5d, 0x7d, 0x3a, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x39, 0x30, 0x30, 0x37, 0x31, 0x39, 0x39, 0x32, 0x35, 0x34, 0x37, 0x34, 0x30, 0x39, 0x39, 0x31, 0x2a, 0x4d, 0x61, 0x74, 0x68, 0x2e, 0x72, 0x61, 0x6e, 0x64, 0x6f, 0x6d, 0x28, 0x29, 0x7d, 0x2c, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x3d, 0x7b, 0x7d, 0x3b, 0x76, 0x61, 0x72, 0x20, 0x71, 0x3d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6e, 0x28, 0x74, 0x2c, 0x65, 0x29, 0x7b, 0x21, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6e, 0x2c, 0x74, 0x29, 0x7b, 0x69, 0x66, 0x28, 0x21, 0x28, 0x6e, 0x20, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x6f, 0x66, 0x20, 0x74, 0x29, 0x29, 0x74, 0x68, 0x72, 0x6f, 0x77, 0x20, 0x6e, 0x65, 0x77, 0x20, 0x54, 0x79, 0x70, 0x65, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x28, 0x22, 0x43, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x20, 0x61, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x20, 0x61, 0x73, 0x20, 0x61, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x29, 0x7d, 0x28, 0x74, 0x68, 0x69, 0x73, 0x2c, 0x6e, 0x29, 0x2c, 0x65, 0x3d, 0x65, 0x7c, 0x7c, 0x2d, 0x31, 0x2c, 0x74, 0x68, 0x69, 0x73, 0x2e, 0x43, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x3d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6e, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x74, 0x2e, 0x61, 0x70, 0x70, 0x6c, 0x79, 0x28, 0x6e, 0x75, 0x6c, 0x6c, 0x2c, 0x6e, 0x29, 0x2c, 0x2d, 0x31, 0x21, 0x3d, 0x3d, 0x65, 0x26, 0x26, 0x30, 0x3d, 0x3d, 0x3d, 0x28, 0x65, 0x2d, 0x3d, 0x31, 0x29, 0x7d, 0x7d, 0x2c, 0x7a, 0x3d, 0x7b, 0x7d, 0x3b, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x56, 0x28, 0x6e, 0x2c, 0x74, 0x2c, 0x65, 0x29, 0x7b, 0x7a, 0x5b, 0x6e, 0x5d, 0x3d, 0x7a, 0x5b, 0x6e, 0x5d, 0x7c, 0x7c, 0x5b, 0x5d, 0x3b, 0x76, 0x61, 0x72, 0x20, 0x72, 0x3d, 0x6e, 0x65, 0x77, 0x20, 0x71, 0x28, 0x74, 0x2c, 0x65, 0x29, 0x3b, 0x63, 0x6f, 0x6e, 0x73, 0x6f, 0x6c, 0x65, 0x2e, 0x6c, 0x6f, 0x67, 0x28, 0x22, 0x50, 0x75, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x20, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x3a, 0x20, 0x22, 0x2b, 0x6e, 0x29, 0x2c, 0x7a, 0x5b, 0x6e, 0x5d, 0x2e, 0x70, 0x75, 0x73, 0x68, 0x28, 0x72, 0x29, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x4b, 0x28, 0x6e, 0x2c, 0x74, 0x29, 0x7b, 0x56, 0x28, 0x6e, 0x2c, 0x74, 0x29, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x51, 0x28, 0x6e, 0x2c, 0x74, 0x29, 0x7b, 0x56, 0x28, 0x6e, 0x2c, 0x74, 0x2c, 0x31, 0x29, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x58, 0x28, 0x6e, 0x29, 0x7b, 0x76, 0x61, 0x72, 0x20, 0x74, 0x3d, 0x6e, 0x2e, 0x6e, 0x61, 0x6d, 0x65, 0x3b, 0x69, 0x66, 0x28, 0x7a, 0x5b, 0x74, 0x5d, 0x29, 0x7b, 0x66, 0x6f, 0x72, 0x28, 0x76, 0x61, 0x72, 0x20, 0x65, 0x3d, 0x7a, 0x5b, 0x74, 0x5d, 0x2e, 0x73, 0x6c, 0x69, 0x63, 0x65, 0x28, 0x29, 0x2c, 0x72, 0x3d, 0x30, 0x3b, 0x72, 0x3c, 0x7a, 0x5b, 0x74, 0x5d, 0x2e, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x3b, 0x72, 0x2b, 0x3d, 0x31, 0x29, 0x7b, 0x76, 0x61, 0x72, 0x20, 0x69, 0x3d, 0x7a, 0x5b, 0x74, 0x5d, 0x5b, 0x72, 0x5d, 0x2c, 0x6f, 0x3d, 0x6e, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x3b, 0x69, 0x2e, 0x43, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x28, 0x6f, 0x29, 0x26, 0x26, 0x65, 0x2e, 0x73, 0x70, 0x6c, 0x69, 0x63, 0x65, 0x28, 0x72, 0x2c, 0x31, 0x29, 0x7d, 0x7a, 0x5b, 0x74, 0x5d, 0x3d, 0x65, 0x7d, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x59, 0x28, 0x6e, 0x29, 0x7b, 0x76, 0x61, 0x72, 0x20, 0x74, 0x3b, 0x74, 0x72, 0x79, 0x7b, 0x74, 0x3d, 0x4a, 0x53, 0x4f, 0x4e, 0x2e, 0x70, 0x61, 0x72, 0x73, 0x65, 0x28, 0x6e, 0x29, 0x7d, 0x63, 0x61, 0x74, 0x63, 0x68, 0x28, 0x74, 0x29, 0x7b, 0x74, 0x68, 0x72, 0x6f, 0x77, 0x20, 0x6e, 0x65, 0x77, 0x20, 0x67, 0x28, 0x22, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x20, 0x4a, 0x53, 0x4f, 0x4e, 0x20, 0x70, 0x61, 0x73, 0x73, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x3a, 0x20, 0x22, 0x2b, 0x6e, 0x29, 0x7d, 0x58, 0x28, 0x74, 0x29, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x5a, 0x28, 0x6e, 0x29, 0x7b, 0x76, 0x61, 0x72, 0x20, 0x74, 0x3d, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x3a, 0x6e, 0x2c, 0x64, 0x61, 0x74, 0x61, 0x3a, 0x5b, 0x5d, 0x2e, 0x73, 0x6c, 0x69, 0x63, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x6c, 0x79, 0x28, 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x29, 0x2e, 0x73, 0x6c, 0x69, 0x63, 0x65, 0x28, 0x31, 0x29, 0x7d, 0x3b, 0x58, 0x28, 0x74, 0x29, 0x2c, 0x64, 0x28, 0x22, 0x45, 0x6a, 0x22, 0x2b, 0x4a, 0x53, 0x4f, 0x4e, 0x2e, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x69, 0x66, 0x79, 0x28, 0x74, 0x29, 0x29, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x24, 0x28, 0x6e, 0x2c, 0x74, 0x29, 0x7b, 0x76, 0x61, 0x72, 0x20, 0x65, 0x3d, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x45, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x28, 0x22, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x22, 0x29, 0x3b, 0x65, 0x2e, 0x74, 0x65, 0x78, 0x74, 0x3d, 0x6e, 0x2c, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x62, 0x6f, 0x64, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x43, 0x68, 0x69, 0x6c, 0x64, 0x28, 0x65, 0x29, 0x2c, 0x74, 0x26, 0x26, 0x5a, 0x28, 0x74, 0x29, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6e, 0x6e, 0x28, 0x6e, 0x29, 0x7b, 0x74, 0x72, 0x79, 0x7b, 0x76, 0x61, 0x72, 0x20, 0x74, 0x3d, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x45, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x28, 0x22, 0x73, 0x74, 0x79, 0x6c, 0x65, 0x22, 0x29, 0x3b, 0x74, 0x2e, 0x73, 0x65, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x28, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x2c, 0x22, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x63, 0x73, 0x73, 0x22, 0x29, 0x2c, 0x74, 0x2e, 0x73, 0x74, 0x79, 0x6c, 0x65, 0x53, 0x68, 0x65, 0x65, 0x74, 0x3f, 0x74, 0x2e, 0x73, 0x74, 0x79, 0x6c, 0x65, 0x53, 0x68, 0x65, 0x65, 0x74, 0x2e, 0x63, 0x73, 0x73, 0x54, 0x65, 0x78, 0x74, 0x3d, 0x6e, 0x3a, 0x74, 0x2e, 0x61, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x43, 0x68, 0x69, 0x6c, 0x64, 0x28, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x65, 0x78, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x28, 0x6e, 0x29, 0x29, 0x2c, 0x28, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x7c, 0x7c, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x67, 0x65, 0x74, 0x45, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x42, 0x79, 0x54, 0x61, 0x67, 0x4e, 0x61, 0x6d, 0x65, 0x28, 0x22, 0x68, 0x65, 0x61, 0x64, 0x22, 0x29, 0x5b, 0x30, 0x5d, 0x29, 0x2e, 0x61, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x43, 0x68, 0x69, 0x6c, 0x64, 0x28, 0x74, 0x29, 0x7d, 0x63, 0x61, 0x74, 0x63, 0x68, 0x28, 0x6e, 0x29, 0x7b, 0x63, 0x6f, 0x6e, 0x73, 0x6f, 0x6c, 0x65, 0x2e, 0x6c, 0x6f, 0x67, 0x28, 0x6e, 0x29, 0x7d, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x74, 0x6e, 0x28, 0x29, 0x7b, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x57, 0x61, 0x69, 0x6c, 0x73, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x4d, 0x65, 0x6e, 0x75, 0x3d, 0x21, 0x30, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x65, 0x6e, 0x28, 0x6e, 0x2c, 0x74, 0x29, 0x7b, 0x76, 0x61, 0x72, 0x20, 0x65, 0x3b, 0x69, 0x66, 0x28, 0x21, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x77, 0x61, 0x69, 0x6c, 0x73, 0x29, 0x74, 0x68, 0x72, 0x6f, 0x77, 0x20, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x28, 0x22, 0x57, 0x61, 0x69, 0x6c, 0x73, 0x20, 0x69, 0x73, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x69, 0x73, 0x65, 0x64, 0x22, 0x29, 0x3b, 0x76, 0x61, 0x72, 0x20, 0x72, 0x3d, 0x5b, 0x5d, 0x3b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x77, 0x61, 0x69, 0x6c, 0x73, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x4f, 0x6e, 0x28, 0x22, 0x77, 0x61, 0x69, 0x6c, 0x73, 0x3a, 0x73, 0x79, 0x6e, 0x63, 0x3a, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x3a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x62, 0x79, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x3a, 0x22, 0x2b, 0x6e, 0x2c, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6e, 0x29, 0x7b, 0x76, 0x61, 0x72, 0x20, 0x74, 0x3d, 0x4a, 0x53, 0x4f, 0x4e, 0x2e, 0x70, 0x61, 0x72, 0x73, 0x65, 0x28, 0x6e, 0x29, 0x3b, 0x65, 0x3d, 0x74, 0x2c, 0x72, 0x2e, 0x66, 0x6f, 0x72, 0x45, 0x61, 0x63, 0x68, 0x28, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6e, 0x29, 0x7b, 0x6e, 0x28, 0x65, 0x29, 0x7d, 0x29, 0x29, 0x7d, 0x29, 0x29, 0x2c, 0x74, 0x26, 0x26, 0x74, 0x68, 0x69, 0x73, 0x2e, 0x73, 0x65, 0x74, 0x28, 0x74, 0x29, 0x2c, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x77, 0x61, 0x69, 0x6c, 0x73, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x45, 0x6d, 0x69, 0x74, 0x28, 0x22, 0x77, 0x61, 0x69, 0x6c, 0x73, 0x3a, 0x73, 0x79, 0x6e, 0x63, 0x3a, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x3a, 0x72, 0x65, 0x73, 0x79, 0x6e, 0x63, 0x3a, 0x22, 0x2b, 0x6e, 0x29, 0x2c, 0x7b, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x3a, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6e, 0x29, 0x7b, 0x72, 0x2e, 0x70, 0x75, 0x73, 0x68, 0x28, 0x6e, 0x29, 0x7d, 0x2c, 0x67, 0x65, 0x74, 0x3a, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x65, 0x7d, 0x2c, 0x73, 0x65, 0x74, 0x3a, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x74, 0x29, 0x7b, 0x65, 0x3d, 0x74, 0x2c, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x77, 0x61, 0x69, 0x6c, 0x73, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x45, 0x6d, 0x69, 0x74, 0x28, 0x22, 0x77, 0x61, 0x69, 0x6c, 0x73, 0x3a, 0x73, 0x79, 0x6e, 0x63, 0x3a, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x3a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x62, 0x79, 0x66, 0x72, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x64, 0x3a, 0x22, 0x2b, 0x6e, 0x2c, 0x4a, 0x53, 0x4f, 0x4e, 0x2e, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x69, 0x66, 0x79, 0x28, 0x65, 0x29, 0x29, 0x2c, 0x72, 0x2e, 0x66, 0x6f, 0x72, 0x45, 0x61, 0x63, 0x68, 0x28, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6e, 0x29, 0x7b, 0x6e, 0x28, 0x65, 0x29, 0x7d, 0x29, 0x29, 0x7d, 0x2c, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6e, 0x29, 0x7b, 0x76, 0x61, 0x72, 0x20, 0x74, 0x3d, 0x6e, 0x28, 0x65, 0x29, 0x3b, 0x74, 0x68, 0x69, 0x73, 0x2e, 0x73, 0x65, 0x74, 0x28, 0x74, 0x29, 0x7d, 0x7d, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x72, 0x6e, 0x28, 0x6e, 0x29, 0x7b, 0x64, 0x28, 0x22, 0x54, 0x49, 0x22, 0x2b, 0x6e, 0x29, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x28, 0x6f, 0x6e, 0x3d, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x61, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x7c, 0x7c, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6e, 0x29, 0x7b, 0x66, 0x6f, 0x72, 0x28, 0x76, 0x61, 0x72, 0x20, 0x74, 0x3d, 0x31, 0x3b, 0x74, 0x3c, 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x3b, 0x74, 0x2b, 0x2b, 0x29, 0x7b, 0x76, 0x61, 0x72, 0x20, 0x65, 0x3d, 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x5b, 0x74, 0x5d, 0x3b, 0x66, 0x6f, 0x72, 0x28, 0x76, 0x61, 0x72, 0x20, 0x72, 0x20, 0x69, 0x6e, 0x20, 0x65, 0x29, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x74, 0x79, 0x70, 0x65, 0x2e, 0x68, 0x61, 0x73, 0x4f, 0x77, 0x6e, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x2e, 0x63, 0x61, 0x6c, 0x6c, 0x28, 0x65, 0x2c, 0x72, 0x29, 0x26, 0x26, 0x28, 0x6e, 0x5b, 0x72, 0x5d, 0x3d, 0x65, 0x5b, 0x72, 0x5d, 0x29, 0x7d, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6e, 0x7d, 0x29, 0x2e, 0x61, 0x70, 0x70, 0x6c, 0x79, 0x28, 0x74, 0x68, 0x69, 0x73, 0x2c, 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x29, 0x7d, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x3d, 0x7b, 0x7d, 0x2c, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x77, 0x61, 0x69, 0x6c, 0x73, 0x3d, 0x7b, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x3a, 0x6c, 0x2c, 0x4c, 0x6f, 0x67, 0x3a, 0x72, 0x2c, 0x42, 0x72, 0x6f, 0x77, 0x73, 0x65, 0x72, 0x3a, 0x69, 0x2c, 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x3a, 0x6f, 0x2c, 0x54, 0x72, 0x61, 0x79, 0x3a, 0x63, 0x2c, 0x44, 0x69, 0x61, 0x6c, 0x6f, 0x67, 0x3a, 0x61, 0x2c, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x3a, 0x7b, 0x4f, 0x6e, 0x3a, 0x4b, 0x2c, 0x4f, 0x6e, 0x63, 0x65, 0x3a, 0x51, 0x2c, 0x4f, 0x6e, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x3a, 0x56, 0x2c, 0x45, 0x6d, 0x69, 0x74, 0x3a, 0x5a, 0x7d, 0x2c, 0x5f, 0x3a, 0x7b, 0x43, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x3a, 0x57, 0x2c, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x3a, 0x59, 0x2c, 0x41, 0x64, 0x64, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x3a, 0x24, 0x2c, 0x49, 0x6e, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x53, 0x53, 0x3a, 0x6e, 0x6e, 0x2c, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x4d, 0x65, 0x6e, 0x75, 0x3a, 0x74, 0x6e, 0x2c, 0x41, 0x64, 0x64, 0x49, 0x50, 0x43, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x3a, 0x66, 0x2c, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x43, 0x61, 0x6c, 0x6c, 0x3a, 0x4d, 0x2c, 0x53, 0x65, 0x6e, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x3a, 0x64, 0x7d, 0x2c, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x3a, 0x75, 0x7d, 0x2c, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x77, 0x61, 0x69, 0x6c, 0x73, 0x2e, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x3d, 0x7b, 0x49, 0x73, 0x44, 0x61, 0x72, 0x6b, 0x4d, 0x6f, 0x64, 0x65, 0x3a, 0x65, 0x6e, 0x28, 0x22, 0x77, 0x61, 0x69, 0x6c, 0x73, 0x3a, 0x69, 0x73, 0x64, 0x61, 0x72, 0x6b, 0x6d, 0x6f, 0x64, 0x65, 0x22, 0x29, 0x2c, 0x4c, 0x6f, 0x67, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x3a, 0x65, 0x6e, 0x28, 0x22, 0x77, 0x61, 0x69, 0x6c, 0x73, 0x3a, 0x6c, 0x6f, 0x67, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x22, 0x29, 0x2c, 0x41, 0x70, 0x70, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x3a, 0x65, 0x6e, 0x28, 0x22, 0x77, 0x61, 0x69, 0x6c, 0x73, 0x3a, 0x61, 0x70, 0x70, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x22, 0x29, 0x7d, 0x2c, 0x6f, 0x6e, 0x28, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x77, 0x61, 0x69, 0x6c, 0x73, 0x2e, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x2c, 0x6c, 0x29, 0x2c, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x61, 0x64, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x28, 0x22, 0x6d, 0x6f, 0x75, 0x73, 0x65, 0x64, 0x6f, 0x77, 0x6e, 0x22, 0x2c, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6e, 0x29, 0x7b, 0x66, 0x6f, 0x72, 0x28, 0x76, 0x61, 0x72, 0x20, 0x74, 0x3d, 0x6e, 0x2e, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x3b, 0x6e, 0x75, 0x6c, 0x6c, 0x21, 0x3d, 0x74, 0x26, 0x26, 0x21, 0x74, 0x2e, 0x68, 0x61, 0x73, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x28, 0x22, 0x64, 0x61, 0x74, 0x61, 0x2d, 0x77, 0x61, 0x69, 0x6c, 0x73, 0x2d, 0x6e, 0x6f, 0x2d, 0x64, 0x72, 0x61, 0x67, 0x22, 0x29, 0x3b, 0x29, 0x7b, 0x69, 0x66, 0x28, 0x74, 0x2e, 0x68, 0x61, 0x73, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x28, 0x22, 0x64, 0x61, 0x74, 0x61, 0x2d, 0x77, 0x61, 0x69, 0x6c, 0x73, 0x2d, 0x64, 0x72, 0x61, 0x67, 0x22, 0x29, 0x29, 0x7b, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x77, 0x61, 0x69, 0x6c, 0x73, 0x44, 0x72, 0x61, 0x67, 0x28, 0x6e, 0x75, 0x6c, 0x6c, 0x29, 0x3b, 0x62, 0x72, 0x65, 0x61, 0x6b, 0x7d, 0x74, 0x3d, 0x74, 0x2e, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x45, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x7d, 0x7d, 0x29, 0x29, 0x2c, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x61, 0x64, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x28, 0x22, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x6d, 0x65, 0x6e, 0x75, 0x22, 0x2c, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6e, 0x29, 0x7b, 0x66, 0x6f, 0x72, 0x28, 0x76, 0x61, 0x72, 0x20, 0x74, 0x2c, 0x65, 0x3d, 0x6e, 0x2e, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x3b, 0x6e, 0x75, 0x6c, 0x6c, 0x21, 0x3d, 0x65, 0x26, 0x26, 0x6e, 0x75, 0x6c, 0x6c, 0x3d, 0x3d, 0x28, 0x74, 0x3d, 0x65, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x73, 0x65, 0x74, 0x5b, 0x22, 0x77, 0x61, 0x69, 0x6c, 0x73, 0x2d, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x2d, 0x6d, 0x65, 0x6e, 0x75, 0x2d, 0x69, 0x64, 0x22, 0x5d, 0x29, 0x3b, 0x29, 0x65, 0x3d, 0x65, 0x2e, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x45, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x3b, 0x69, 0x66, 0x28, 0x28, 0x6e, 0x75, 0x6c, 0x6c, 0x21, 0x3d, 0x74, 0x7c, 0x7c, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x57, 0x61, 0x69, 0x6c, 0x73, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x4d, 0x65, 0x6e, 0x75, 0x29, 0x26, 0x26, 0x6e, 0x2e, 0x70, 0x72, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x28, 0x29, 0x2c, 0x6e, 0x75, 0x6c, 0x6c, 0x21, 0x3d, 0x74, 0x29, 0x7b, 0x76, 0x61, 0x72, 0x20, 0x72, 0x3d, 0x7b, 0x69, 0x64, 0x3a, 0x74, 0x2c, 0x64, 0x61, 0x74, 0x61, 0x3a, 0x65, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x73, 0x65, 0x74, 0x5b, 0x22, 0x77, 0x61, 0x69, 0x6c, 0x73, 0x2d, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x2d, 0x6d, 0x65, 0x6e, 0x75, 0x2d, 0x64, 0x61, 0x74, 0x61, 0x22, 0x5d, 0x7c, 0x7c, 0x22, 0x22, 0x7d, 0x3b, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x77, 0x61, 0x69, 0x6c, 0x73, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x4d, 0x65, 0x6e, 0x75, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x28, 0x4a, 0x53, 0x4f, 0x4e, 0x2e, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x69, 0x66, 0x79, 0x28, 0x72, 0x29, 0x29, 0x7d, 0x7d, 0x29, 0x29, 0x2c, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x77, 0x61, 0x69, 0x6c, 0x73, 0x62, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x73, 0x26, 0x26, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6e, 0x29, 0x7b, 0x74, 0x72, 0x79, 0x7b, 0x6e, 0x3d, 0x4a, 0x53, 0x4f, 0x4e, 0x2e, 0x70, 0x61, 0x72, 0x73, 0x65, 0x28, 0x6e, 0x29, 0x7d, 0x63, 0x61, 0x74, 0x63, 0x68, 0x28, 0x6e, 0x29, 0x7b, 0x63, 0x6f, 0x6e, 0x73, 0x6f, 0x6c, 0x65, 0x2e, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x28, 0x6e, 0x29, 0x7d, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x3d, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x7c, 0x7c, 0x7b, 0x7d, 0x2c, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x6b, 0x65, 0x79, 0x73, 0x28, 0x6e, 0x29, 0x2e, 0x66, 0x6f, 0x72, 0x45, 0x61, 0x63, 0x68, 0x28, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x74, 0x29, 0x7b, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x5b, 0x74, 0x5d, 0x3d, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x5b, 0x74, 0x5d, 0x7c, 0x7c, 0x7b, 0x7d, 0x2c, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x6b, 0x65, 0x79, 0x73, 0x28, 0x6e, 0x5b, 0x74, 0x5d, 0x29, 0x2e, 0x66, 0x6f, 0x72, 0x45, 0x61, 0x63, 0x68, 0x28, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x65, 0x29, 0x7b, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x5b, 0x74, 0x5d, 0x5b, 0x65, 0x5d, 0x3d, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x5b, 0x74, 0x5d, 0x5b, 0x65, 0x5d, 0x7c, 0x7c, 0x7b, 0x7d, 0x2c, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x6b, 0x65, 0x79, 0x73, 0x28, 0x6e, 0x5b, 0x74, 0x5d, 0x5b, 0x65, 0x5d, 0x29, 0x2e, 0x66, 0x6f, 0x72, 0x45, 0x61, 0x63, 0x68, 0x28, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6e, 0x29, 0x7b, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x5b, 0x74, 0x5d, 0x5b, 0x65, 0x5d, 0x5b, 0x6e, 0x5d, 0x3d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x76, 0x61, 0x72, 0x20, 0x72, 0x3d, 0x30, 0x3b, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x69, 0x28, 0x29, 0x7b, 0x76, 0x61, 0x72, 0x20, 0x69, 0x3d, 0x5b, 0x5d, 0x2e, 0x73, 0x6c, 0x69, 0x63, 0x65, 0x2e, 0x63, 0x61, 0x6c, 0x6c, 0x28, 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x29, 0x3b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x43, 0x28, 0x5b, 0x74, 0x2c, 0x65, 0x2c, 0x6e, 0x5d, 0x2e, 0x6a, 0x6f, 0x69, 0x6e, 0x28, 0x22, 0x2e, 0x22, 0x29, 0x2c, 0x69, 0x2c, 0x72, 0x29, 0x7d, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x69, 0x2e, 0x73, 0x65, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x3d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6e, 0x29, 0x7b, 0x72, 0x3d, 0x6e, 0x7d, 0x2c, 0x69, 0x2e, 0x67, 0x65, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x3d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x72, 0x7d, 0x2c, 0x69, 0x7d, 0x28, 0x29, 0x7d, 0x29, 0x29, 0x7d, 0x29, 0x29, 0x7d, 0x29, 0x29, 0x7d, 0x28, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x77, 0x61, 0x69, 0x6c, 0x73, 0x62, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x73, 0x29, 0x2c, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x77, 0x61, 0x69, 0x6c, 0x73, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x45, 0x6d, 0x69, 0x74, 0x28, 0x22, 0x77, 0x61, 0x69, 0x6c, 0x73, 0x3a, 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x64, 0x22, 0x29, 0x7d, 0x5d, 0x29, 0x3b, 0x00};
\ No newline at end of file
diff --git a/v2/internal/ffenestri/runtime_linux.c b/v2/internal/ffenestri/runtime_linux.c
new file mode 100644
index 000000000..a8eb668be
--- /dev/null
+++ b/v2/internal/ffenestri/runtime_linux.c
@@ -0,0 +1,5 @@
+
+// runtime.c (c) 2019-Present Lea Anthony.
+// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
+// This file was auto-generated. DO NOT MODIFY.
+const unsigned char runtime[]={0x76, 0x61, 0x72, 0x20, 0x57, 0x61, 0x69, 0x6c, 0x73, 0x3d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6e, 0x29, 0x7b, 0x76, 0x61, 0x72, 0x20, 0x74, 0x3d, 0x7b, 0x7d, 0x3b, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x65, 0x28, 0x72, 0x29, 0x7b, 0x69, 0x66, 0x28, 0x74, 0x5b, 0x72, 0x5d, 0x29, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x74, 0x5b, 0x72, 0x5d, 0x2e, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x73, 0x3b, 0x76, 0x61, 0x72, 0x20, 0x69, 0x3d, 0x74, 0x5b, 0x72, 0x5d, 0x3d, 0x7b, 0x69, 0x3a, 0x72, 0x2c, 0x6c, 0x3a, 0x21, 0x31, 0x2c, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x73, 0x3a, 0x7b, 0x7d, 0x7d, 0x3b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6e, 0x5b, 0x72, 0x5d, 0x2e, 0x63, 0x61, 0x6c, 0x6c, 0x28, 0x69, 0x2e, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x73, 0x2c, 0x69, 0x2c, 0x69, 0x2e, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x73, 0x2c, 0x65, 0x29, 0x2c, 0x69, 0x2e, 0x6c, 0x3d, 0x21, 0x30, 0x2c, 0x69, 0x2e, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x73, 0x7d, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x65, 0x2e, 0x6d, 0x3d, 0x6e, 0x2c, 0x65, 0x2e, 0x63, 0x3d, 0x74, 0x2c, 0x65, 0x2e, 0x64, 0x3d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6e, 0x2c, 0x74, 0x2c, 0x72, 0x29, 0x7b, 0x65, 0x2e, 0x6f, 0x28, 0x6e, 0x2c, 0x74, 0x29, 0x7c, 0x7c, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x28, 0x6e, 0x2c, 0x74, 0x2c, 0x7b, 0x65, 0x6e, 0x75, 0x6d, 0x65, 0x72, 0x61, 0x62, 0x6c, 0x65, 0x3a, 0x21, 0x30, 0x2c, 0x67, 0x65, 0x74, 0x3a, 0x72, 0x7d, 0x29, 0x7d, 0x2c, 0x65, 0x2e, 0x72, 0x3d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6e, 0x29, 0x7b, 0x22, 0x75, 0x6e, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, 0x22, 0x21, 0x3d, 0x74, 0x79, 0x70, 0x65, 0x6f, 0x66, 0x20, 0x53, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x26, 0x26, 0x53, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x2e, 0x74, 0x6f, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x54, 0x61, 0x67, 0x26, 0x26, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x28, 0x6e, 0x2c, 0x53, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x2e, 0x74, 0x6f, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x54, 0x61, 0x67, 0x2c, 0x7b, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x22, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x22, 0x7d, 0x29, 0x2c, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x28, 0x6e, 0x2c, 0x22, 0x5f, 0x5f, 0x65, 0x73, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x22, 0x2c, 0x7b, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x21, 0x30, 0x7d, 0x29, 0x7d, 0x2c, 0x65, 0x2e, 0x74, 0x3d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6e, 0x2c, 0x74, 0x29, 0x7b, 0x69, 0x66, 0x28, 0x31, 0x26, 0x74, 0x26, 0x26, 0x28, 0x6e, 0x3d, 0x65, 0x28, 0x6e, 0x29, 0x29, 0x2c, 0x38, 0x26, 0x74, 0x29, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6e, 0x3b, 0x69, 0x66, 0x28, 0x34, 0x26, 0x74, 0x26, 0x26, 0x22, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x22, 0x3d, 0x3d, 0x74, 0x79, 0x70, 0x65, 0x6f, 0x66, 0x20, 0x6e, 0x26, 0x26, 0x6e, 0x26, 0x26, 0x6e, 0x2e, 0x5f, 0x5f, 0x65, 0x73, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x29, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6e, 0x3b, 0x76, 0x61, 0x72, 0x20, 0x72, 0x3d, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x28, 0x6e, 0x75, 0x6c, 0x6c, 0x29, 0x3b, 0x69, 0x66, 0x28, 0x65, 0x2e, 0x72, 0x28, 0x72, 0x29, 0x2c, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x28, 0x72, 0x2c, 0x22, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x22, 0x2c, 0x7b, 0x65, 0x6e, 0x75, 0x6d, 0x65, 0x72, 0x61, 0x62, 0x6c, 0x65, 0x3a, 0x21, 0x30, 0x2c, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x6e, 0x7d, 0x29, 0x2c, 0x32, 0x26, 0x74, 0x26, 0x26, 0x22, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x22, 0x21, 0x3d, 0x74, 0x79, 0x70, 0x65, 0x6f, 0x66, 0x20, 0x6e, 0x29, 0x66, 0x6f, 0x72, 0x28, 0x76, 0x61, 0x72, 0x20, 0x69, 0x20, 0x69, 0x6e, 0x20, 0x6e, 0x29, 0x65, 0x2e, 0x64, 0x28, 0x72, 0x2c, 0x69, 0x2c, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x74, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6e, 0x5b, 0x74, 0x5d, 0x7d, 0x2e, 0x62, 0x69, 0x6e, 0x64, 0x28, 0x6e, 0x75, 0x6c, 0x6c, 0x2c, 0x69, 0x29, 0x29, 0x3b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x72, 0x7d, 0x2c, 0x65, 0x2e, 0x6e, 0x3d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6e, 0x29, 0x7b, 0x76, 0x61, 0x72, 0x20, 0x74, 0x3d, 0x6e, 0x26, 0x26, 0x6e, 0x2e, 0x5f, 0x5f, 0x65, 0x73, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x3f, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6e, 0x2e, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x7d, 0x3a, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6e, 0x7d, 0x3b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x65, 0x2e, 0x64, 0x28, 0x74, 0x2c, 0x22, 0x61, 0x22, 0x2c, 0x74, 0x29, 0x2c, 0x74, 0x7d, 0x2c, 0x65, 0x2e, 0x6f, 0x3d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6e, 0x2c, 0x74, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x74, 0x79, 0x70, 0x65, 0x2e, 0x68, 0x61, 0x73, 0x4f, 0x77, 0x6e, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x2e, 0x63, 0x61, 0x6c, 0x6c, 0x28, 0x6e, 0x2c, 0x74, 0x29, 0x7d, 0x2c, 0x65, 0x2e, 0x70, 0x3d, 0x22, 0x22, 0x2c, 0x65, 0x28, 0x65, 0x2e, 0x73, 0x3d, 0x30, 0x29, 0x7d, 0x28, 0x5b, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6e, 0x2c, 0x74, 0x2c, 0x65, 0x29, 0x7b, 0x22, 0x75, 0x73, 0x65, 0x20, 0x73, 0x74, 0x72, 0x69, 0x63, 0x74, 0x22, 0x3b, 0x65, 0x2e, 0x72, 0x28, 0x74, 0x29, 0x3b, 0x76, 0x61, 0x72, 0x20, 0x72, 0x3d, 0x7b, 0x7d, 0x3b, 0x65, 0x2e, 0x72, 0x28, 0x72, 0x29, 0x2c, 0x65, 0x2e, 0x64, 0x28, 0x72, 0x2c, 0x22, 0x54, 0x72, 0x61, 0x63, 0x65, 0x22, 0x2c, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x76, 0x7d, 0x29, 0x29, 0x2c, 0x65, 0x2e, 0x64, 0x28, 0x72, 0x2c, 0x22, 0x50, 0x72, 0x69, 0x6e, 0x74, 0x22, 0x2c, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x70, 0x7d, 0x29, 0x29, 0x2c, 0x65, 0x2e, 0x64, 0x28, 0x72, 0x2c, 0x22, 0x44, 0x65, 0x62, 0x75, 0x67, 0x22, 0x2c, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x79, 0x7d, 0x29, 0x29, 0x2c, 0x65, 0x2e, 0x64, 0x28, 0x72, 0x2c, 0x22, 0x49, 0x6e, 0x66, 0x6f, 0x22, 0x2c, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6d, 0x7d, 0x29, 0x29, 0x2c, 0x65, 0x2e, 0x64, 0x28, 0x72, 0x2c, 0x22, 0x57, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x22, 0x2c, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x62, 0x7d, 0x29, 0x29, 0x2c, 0x65, 0x2e, 0x64, 0x28, 0x72, 0x2c, 0x22, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x2c, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x67, 0x7d, 0x29, 0x29, 0x2c, 0x65, 0x2e, 0x64, 0x28, 0x72, 0x2c, 0x22, 0x46, 0x61, 0x74, 0x61, 0x6c, 0x22, 0x2c, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x68, 0x7d, 0x29, 0x29, 0x2c, 0x65, 0x2e, 0x64, 0x28, 0x72, 0x2c, 0x22, 0x53, 0x65, 0x74, 0x4c, 0x6f, 0x67, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x22, 0x2c, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x53, 0x7d, 0x29, 0x29, 0x2c, 0x65, 0x2e, 0x64, 0x28, 0x72, 0x2c, 0x22, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x22, 0x2c, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x45, 0x7d, 0x29, 0x29, 0x3b, 0x76, 0x61, 0x72, 0x20, 0x69, 0x3d, 0x7b, 0x7d, 0x3b, 0x65, 0x2e, 0x72, 0x28, 0x69, 0x29, 0x2c, 0x65, 0x2e, 0x64, 0x28, 0x69, 0x2c, 0x22, 0x4f, 0x70, 0x65, 0x6e, 0x22, 0x2c, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x4d, 0x7d, 0x29, 0x29, 0x3b, 0x76, 0x61, 0x72, 0x20, 0x6f, 0x3d, 0x7b, 0x7d, 0x3b, 0x65, 0x2e, 0x72, 0x28, 0x6f, 0x29, 0x2c, 0x65, 0x2e, 0x64, 0x28, 0x6f, 0x2c, 0x22, 0x43, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x22, 0x2c, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x4e, 0x7d, 0x29, 0x29, 0x2c, 0x65, 0x2e, 0x64, 0x28, 0x6f, 0x2c, 0x22, 0x53, 0x65, 0x74, 0x54, 0x69, 0x74, 0x6c, 0x65, 0x22, 0x2c, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x54, 0x7d, 0x29, 0x29, 0x2c, 0x65, 0x2e, 0x64, 0x28, 0x6f, 0x2c, 0x22, 0x46, 0x75, 0x6c, 0x6c, 0x73, 0x63, 0x72, 0x65, 0x65, 0x6e, 0x22, 0x2c, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6a, 0x7d, 0x29, 0x29, 0x2c, 0x65, 0x2e, 0x64, 0x28, 0x6f, 0x2c, 0x22, 0x55, 0x6e, 0x46, 0x75, 0x6c, 0x6c, 0x73, 0x63, 0x72, 0x65, 0x65, 0x6e, 0x22, 0x2c, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x44, 0x7d, 0x29, 0x29, 0x2c, 0x65, 0x2e, 0x64, 0x28, 0x6f, 0x2c, 0x22, 0x53, 0x65, 0x74, 0x53, 0x69, 0x7a, 0x65, 0x22, 0x2c, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x49, 0x7d, 0x29, 0x29, 0x2c, 0x65, 0x2e, 0x64, 0x28, 0x6f, 0x2c, 0x22, 0x53, 0x65, 0x74, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x2c, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x50, 0x7d, 0x29, 0x29, 0x2c, 0x65, 0x2e, 0x64, 0x28, 0x6f, 0x2c, 0x22, 0x48, 0x69, 0x64, 0x65, 0x22, 0x2c, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x41, 0x7d, 0x29, 0x29, 0x2c, 0x65, 0x2e, 0x64, 0x28, 0x6f, 0x2c, 0x22, 0x53, 0x68, 0x6f, 0x77, 0x22, 0x2c, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x4a, 0x7d, 0x29, 0x29, 0x2c, 0x65, 0x2e, 0x64, 0x28, 0x6f, 0x2c, 0x22, 0x4d, 0x61, 0x78, 0x69, 0x6d, 0x69, 0x73, 0x65, 0x22, 0x2c, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x4c, 0x7d, 0x29, 0x29, 0x2c, 0x65, 0x2e, 0x64, 0x28, 0x6f, 0x2c, 0x22, 0x55, 0x6e, 0x6d, 0x61, 0x78, 0x69, 0x6d, 0x69, 0x73, 0x65, 0x22, 0x2c, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x52, 0x7d, 0x29, 0x29, 0x2c, 0x65, 0x2e, 0x64, 0x28, 0x6f, 0x2c, 0x22, 0x4d, 0x69, 0x6e, 0x69, 0x6d, 0x69, 0x73, 0x65, 0x22, 0x2c, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x5f, 0x7d, 0x29, 0x29, 0x2c, 0x65, 0x2e, 0x64, 0x28, 0x6f, 0x2c, 0x22, 0x55, 0x6e, 0x6d, 0x69, 0x6e, 0x69, 0x6d, 0x69, 0x73, 0x65, 0x22, 0x2c, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x46, 0x7d, 0x29, 0x29, 0x2c, 0x65, 0x2e, 0x64, 0x28, 0x6f, 0x2c, 0x22, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x22, 0x2c, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x55, 0x7d, 0x29, 0x29, 0x3b, 0x76, 0x61, 0x72, 0x20, 0x61, 0x3d, 0x7b, 0x7d, 0x3b, 0x65, 0x2e, 0x72, 0x28, 0x61, 0x29, 0x2c, 0x65, 0x2e, 0x64, 0x28, 0x61, 0x2c, 0x22, 0x4f, 0x70, 0x65, 0x6e, 0x22, 0x2c, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x42, 0x7d, 0x29, 0x29, 0x2c, 0x65, 0x2e, 0x64, 0x28, 0x61, 0x2c, 0x22, 0x53, 0x61, 0x76, 0x65, 0x22, 0x2c, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x48, 0x7d, 0x29, 0x29, 0x2c, 0x65, 0x2e, 0x64, 0x28, 0x61, 0x2c, 0x22, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x2c, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x47, 0x7d, 0x29, 0x29, 0x3b, 0x76, 0x61, 0x72, 0x20, 0x75, 0x3d, 0x7b, 0x7d, 0x3b, 0x65, 0x2e, 0x72, 0x28, 0x75, 0x29, 0x2c, 0x65, 0x2e, 0x64, 0x28, 0x75, 0x2c, 0x22, 0x4e, 0x65, 0x77, 0x22, 0x2c, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x65, 0x6e, 0x7d, 0x29, 0x29, 0x3b, 0x76, 0x61, 0x72, 0x20, 0x63, 0x3d, 0x7b, 0x7d, 0x3b, 0x65, 0x2e, 0x72, 0x28, 0x63, 0x29, 0x2c, 0x65, 0x2e, 0x64, 0x28, 0x63, 0x2c, 0x22, 0x53, 0x65, 0x74, 0x49, 0x63, 0x6f, 0x6e, 0x22, 0x2c, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x72, 0x6e, 0x7d, 0x29, 0x29, 0x3b, 0x76, 0x61, 0x72, 0x20, 0x6c, 0x3d, 0x7b, 0x41, 0x70, 0x70, 0x54, 0x79, 0x70, 0x65, 0x3a, 0x22, 0x64, 0x65, 0x73, 0x6b, 0x74, 0x6f, 0x70, 0x22, 0x2c, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x3a, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x22, 0x6c, 0x69, 0x6e, 0x75, 0x78, 0x22, 0x7d, 0x7d, 0x3b, 0x76, 0x61, 0x72, 0x20, 0x73, 0x3d, 0x5b, 0x5d, 0x3b, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x66, 0x28, 0x6e, 0x29, 0x7b, 0x73, 0x2e, 0x70, 0x75, 0x73, 0x68, 0x28, 0x6e, 0x29, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x64, 0x28, 0x6e, 0x29, 0x7b, 0x69, 0x66, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6e, 0x29, 0x7b, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x77, 0x61, 0x69, 0x6c, 0x73, 0x49, 0x6e, 0x76, 0x6f, 0x6b, 0x65, 0x28, 0x6e, 0x29, 0x7d, 0x28, 0x6e, 0x29, 0x2c, 0x73, 0x2e, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x3e, 0x30, 0x29, 0x66, 0x6f, 0x72, 0x28, 0x76, 0x61, 0x72, 0x20, 0x74, 0x3d, 0x30, 0x3b, 0x74, 0x3c, 0x73, 0x2e, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x3b, 0x74, 0x2b, 0x2b, 0x29, 0x73, 0x5b, 0x74, 0x5d, 0x28, 0x6e, 0x29, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x77, 0x28, 0x6e, 0x2c, 0x74, 0x29, 0x7b, 0x64, 0x28, 0x22, 0x4c, 0x22, 0x2b, 0x6e, 0x2b, 0x74, 0x29, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x76, 0x28, 0x6e, 0x29, 0x7b, 0x77, 0x28, 0x22, 0x54, 0x22, 0x2c, 0x6e, 0x29, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x70, 0x28, 0x6e, 0x29, 0x7b, 0x77, 0x28, 0x22, 0x50, 0x22, 0x2c, 0x6e, 0x29, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x79, 0x28, 0x6e, 0x29, 0x7b, 0x77, 0x28, 0x22, 0x44, 0x22, 0x2c, 0x6e, 0x29, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6d, 0x28, 0x6e, 0x29, 0x7b, 0x77, 0x28, 0x22, 0x49, 0x22, 0x2c, 0x6e, 0x29, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x62, 0x28, 0x6e, 0x29, 0x7b, 0x77, 0x28, 0x22, 0x57, 0x22, 0x2c, 0x6e, 0x29, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x67, 0x28, 0x6e, 0x29, 0x7b, 0x77, 0x28, 0x22, 0x45, 0x22, 0x2c, 0x6e, 0x29, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x68, 0x28, 0x6e, 0x29, 0x7b, 0x77, 0x28, 0x22, 0x46, 0x22, 0x2c, 0x6e, 0x29, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x53, 0x28, 0x6e, 0x29, 0x7b, 0x77, 0x28, 0x22, 0x53, 0x22, 0x2c, 0x6e, 0x29, 0x7d, 0x76, 0x61, 0x72, 0x20, 0x4f, 0x2c, 0x45, 0x3d, 0x7b, 0x54, 0x52, 0x41, 0x43, 0x45, 0x3a, 0x31, 0x2c, 0x44, 0x45, 0x42, 0x55, 0x47, 0x3a, 0x32, 0x2c, 0x49, 0x4e, 0x46, 0x4f, 0x3a, 0x33, 0x2c, 0x57, 0x41, 0x52, 0x4e, 0x49, 0x4e, 0x47, 0x3a, 0x34, 0x2c, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x3a, 0x35, 0x7d, 0x2c, 0x6b, 0x3d, 0x7b, 0x7d, 0x3b, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x43, 0x28, 0x6e, 0x2c, 0x74, 0x2c, 0x65, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6e, 0x75, 0x6c, 0x6c, 0x21, 0x3d, 0x65, 0x26, 0x26, 0x6e, 0x75, 0x6c, 0x6c, 0x21, 0x3d, 0x65, 0x7c, 0x7c, 0x28, 0x65, 0x3d, 0x30, 0x29, 0x2c, 0x6e, 0x65, 0x77, 0x20, 0x50, 0x72, 0x6f, 0x6d, 0x69, 0x73, 0x65, 0x28, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x72, 0x2c, 0x69, 0x29, 0x7b, 0x76, 0x61, 0x72, 0x20, 0x6f, 0x3b, 0x64, 0x6f, 0x7b, 0x6f, 0x3d, 0x6e, 0x2b, 0x22, 0x2d, 0x22, 0x2b, 0x4f, 0x28, 0x29, 0x7d, 0x77, 0x68, 0x69, 0x6c, 0x65, 0x28, 0x6b, 0x5b, 0x6f, 0x5d, 0x29, 0x3b, 0x69, 0x66, 0x28, 0x65, 0x3e, 0x30, 0x29, 0x76, 0x61, 0x72, 0x20, 0x61, 0x3d, 0x73, 0x65, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x28, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x69, 0x28, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x28, 0x22, 0x43, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x6f, 0x20, 0x22, 0x2b, 0x6e, 0x2b, 0x22, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x64, 0x20, 0x6f, 0x75, 0x74, 0x2e, 0x20, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x20, 0x49, 0x44, 0x3a, 0x20, 0x22, 0x2b, 0x6f, 0x29, 0x29, 0x7d, 0x29, 0x2c, 0x65, 0x29, 0x3b, 0x6b, 0x5b, 0x6f, 0x5d, 0x3d, 0x7b, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x3a, 0x61, 0x2c, 0x72, 0x65, 0x6a, 0x65, 0x63, 0x74, 0x3a, 0x69, 0x2c, 0x72, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x3a, 0x72, 0x7d, 0x3b, 0x74, 0x72, 0x79, 0x7b, 0x76, 0x61, 0x72, 0x20, 0x75, 0x3d, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x3a, 0x6e, 0x2c, 0x61, 0x72, 0x67, 0x73, 0x3a, 0x74, 0x2c, 0x63, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x49, 0x44, 0x3a, 0x6f, 0x7d, 0x3b, 0x64, 0x28, 0x22, 0x43, 0x22, 0x2b, 0x4a, 0x53, 0x4f, 0x4e, 0x2e, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x69, 0x66, 0x79, 0x28, 0x75, 0x29, 0x29, 0x7d, 0x63, 0x61, 0x74, 0x63, 0x68, 0x28, 0x6e, 0x29, 0x7b, 0x63, 0x6f, 0x6e, 0x73, 0x6f, 0x6c, 0x65, 0x2e, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x28, 0x6e, 0x29, 0x7d, 0x7d, 0x29, 0x29, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x57, 0x28, 0x6e, 0x29, 0x7b, 0x76, 0x61, 0x72, 0x20, 0x74, 0x3b, 0x74, 0x72, 0x79, 0x7b, 0x74, 0x3d, 0x4a, 0x53, 0x4f, 0x4e, 0x2e, 0x70, 0x61, 0x72, 0x73, 0x65, 0x28, 0x6e, 0x29, 0x7d, 0x63, 0x61, 0x74, 0x63, 0x68, 0x28, 0x74, 0x29, 0x7b, 0x76, 0x61, 0x72, 0x20, 0x65, 0x3d, 0x22, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x20, 0x4a, 0x53, 0x4f, 0x4e, 0x20, 0x70, 0x61, 0x73, 0x73, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x3a, 0x20, 0x22, 0x2e, 0x63, 0x6f, 0x6e, 0x63, 0x61, 0x74, 0x28, 0x74, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2c, 0x22, 0x2e, 0x20, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x3a, 0x20, 0x22, 0x29, 0x2e, 0x63, 0x6f, 0x6e, 0x63, 0x61, 0x74, 0x28, 0x6e, 0x29, 0x3b, 0x74, 0x68, 0x72, 0x6f, 0x77, 0x20, 0x79, 0x28, 0x65, 0x29, 0x2c, 0x6e, 0x65, 0x77, 0x20, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x28, 0x65, 0x29, 0x7d, 0x76, 0x61, 0x72, 0x20, 0x72, 0x3d, 0x74, 0x2e, 0x63, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x69, 0x64, 0x2c, 0x69, 0x3d, 0x6b, 0x5b, 0x72, 0x5d, 0x3b, 0x69, 0x66, 0x28, 0x21, 0x69, 0x29, 0x7b, 0x76, 0x61, 0x72, 0x20, 0x6f, 0x3d, 0x22, 0x43, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x20, 0x27, 0x22, 0x2e, 0x63, 0x6f, 0x6e, 0x63, 0x61, 0x74, 0x28, 0x72, 0x2c, 0x22, 0x27, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x21, 0x21, 0x21, 0x22, 0x29, 0x3b, 0x74, 0x68, 0x72, 0x6f, 0x77, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x6f, 0x6c, 0x65, 0x2e, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x28, 0x6f, 0x29, 0x2c, 0x6e, 0x65, 0x77, 0x20, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x28, 0x6f, 0x29, 0x7d, 0x63, 0x6c, 0x65, 0x61, 0x72, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x28, 0x69, 0x2e, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x29, 0x2c, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x20, 0x6b, 0x5b, 0x72, 0x5d, 0x2c, 0x74, 0x2e, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x3f, 0x69, 0x2e, 0x72, 0x65, 0x6a, 0x65, 0x63, 0x74, 0x28, 0x74, 0x2e, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x29, 0x3a, 0x69, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x28, 0x74, 0x2e, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x29, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x78, 0x28, 0x6e, 0x29, 0x7b, 0x76, 0x61, 0x72, 0x20, 0x74, 0x3d, 0x5b, 0x5d, 0x2e, 0x73, 0x6c, 0x69, 0x63, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x6c, 0x79, 0x28, 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x29, 0x2e, 0x73, 0x6c, 0x69, 0x63, 0x65, 0x28, 0x31, 0x29, 0x3b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x43, 0x28, 0x22, 0x2e, 0x77, 0x61, 0x69, 0x6c, 0x73, 0x2e, 0x22, 0x2b, 0x6e, 0x2c, 0x74, 0x29, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x4d, 0x28, 0x6e, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x64, 0x28, 0x22, 0x52, 0x42, 0x4f, 0x22, 0x2b, 0x6e, 0x29, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x4e, 0x28, 0x29, 0x7b, 0x64, 0x28, 0x22, 0x57, 0x63, 0x22, 0x29, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x54, 0x28, 0x6e, 0x29, 0x7b, 0x64, 0x28, 0x22, 0x57, 0x54, 0x22, 0x2b, 0x6e, 0x29, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6a, 0x28, 0x29, 0x7b, 0x64, 0x28, 0x22, 0x57, 0x46, 0x22, 0x29, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x44, 0x28, 0x29, 0x7b, 0x64, 0x28, 0x22, 0x57, 0x66, 0x22, 0x29, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x49, 0x28, 0x6e, 0x2c, 0x74, 0x29, 0x7b, 0x64, 0x28, 0x22, 0x57, 0x73, 0x3a, 0x22, 0x2b, 0x6e, 0x2b, 0x22, 0x3a, 0x22, 0x2b, 0x74, 0x29, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x50, 0x28, 0x6e, 0x2c, 0x74, 0x29, 0x7b, 0x64, 0x28, 0x22, 0x57, 0x70, 0x3a, 0x22, 0x2b, 0x6e, 0x2b, 0x22, 0x3a, 0x22, 0x2b, 0x74, 0x29, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x28, 0x29, 0x7b, 0x64, 0x28, 0x22, 0x57, 0x48, 0x22, 0x29, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x4a, 0x28, 0x29, 0x7b, 0x64, 0x28, 0x22, 0x57, 0x53, 0x22, 0x29, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x4c, 0x28, 0x29, 0x7b, 0x64, 0x28, 0x22, 0x57, 0x4d, 0x22, 0x29, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x52, 0x28, 0x29, 0x7b, 0x64, 0x28, 0x22, 0x57, 0x55, 0x22, 0x29, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x5f, 0x28, 0x29, 0x7b, 0x64, 0x28, 0x22, 0x57, 0x6d, 0x22, 0x29, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x46, 0x28, 0x29, 0x7b, 0x64, 0x28, 0x22, 0x57, 0x75, 0x22, 0x29, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x55, 0x28, 0x29, 0x7b, 0x64, 0x28, 0x22, 0x57, 0x43, 0x22, 0x29, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x42, 0x28, 0x6e, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x78, 0x28, 0x22, 0x44, 0x69, 0x61, 0x6c, 0x6f, 0x67, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x22, 0x2c, 0x6e, 0x29, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x48, 0x28, 0x6e, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x78, 0x28, 0x22, 0x44, 0x69, 0x61, 0x6c, 0x6f, 0x67, 0x2e, 0x53, 0x61, 0x76, 0x65, 0x22, 0x2c, 0x6e, 0x29, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x47, 0x28, 0x6e, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x78, 0x28, 0x22, 0x44, 0x69, 0x61, 0x6c, 0x6f, 0x67, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x2c, 0x6e, 0x29, 0x7d, 0x4f, 0x3d, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x3f, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x76, 0x61, 0x72, 0x20, 0x6e, 0x3d, 0x6e, 0x65, 0x77, 0x20, 0x55, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x41, 0x72, 0x72, 0x61, 0x79, 0x28, 0x31, 0x29, 0x3b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x67, 0x65, 0x74, 0x52, 0x61, 0x6e, 0x64, 0x6f, 0x6d, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x28, 0x6e, 0x29, 0x5b, 0x30, 0x5d, 0x7d, 0x3a, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x39, 0x30, 0x30, 0x37, 0x31, 0x39, 0x39, 0x32, 0x35, 0x34, 0x37, 0x34, 0x30, 0x39, 0x39, 0x31, 0x2a, 0x4d, 0x61, 0x74, 0x68, 0x2e, 0x72, 0x61, 0x6e, 0x64, 0x6f, 0x6d, 0x28, 0x29, 0x7d, 0x2c, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x3d, 0x7b, 0x7d, 0x3b, 0x76, 0x61, 0x72, 0x20, 0x71, 0x3d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6e, 0x28, 0x74, 0x2c, 0x65, 0x29, 0x7b, 0x21, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6e, 0x2c, 0x74, 0x29, 0x7b, 0x69, 0x66, 0x28, 0x21, 0x28, 0x6e, 0x20, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x6f, 0x66, 0x20, 0x74, 0x29, 0x29, 0x74, 0x68, 0x72, 0x6f, 0x77, 0x20, 0x6e, 0x65, 0x77, 0x20, 0x54, 0x79, 0x70, 0x65, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x28, 0x22, 0x43, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x20, 0x61, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x20, 0x61, 0x73, 0x20, 0x61, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x29, 0x7d, 0x28, 0x74, 0x68, 0x69, 0x73, 0x2c, 0x6e, 0x29, 0x2c, 0x65, 0x3d, 0x65, 0x7c, 0x7c, 0x2d, 0x31, 0x2c, 0x74, 0x68, 0x69, 0x73, 0x2e, 0x43, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x3d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6e, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x74, 0x2e, 0x61, 0x70, 0x70, 0x6c, 0x79, 0x28, 0x6e, 0x75, 0x6c, 0x6c, 0x2c, 0x6e, 0x29, 0x2c, 0x2d, 0x31, 0x21, 0x3d, 0x3d, 0x65, 0x26, 0x26, 0x30, 0x3d, 0x3d, 0x3d, 0x28, 0x65, 0x2d, 0x3d, 0x31, 0x29, 0x7d, 0x7d, 0x2c, 0x7a, 0x3d, 0x7b, 0x7d, 0x3b, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x56, 0x28, 0x6e, 0x2c, 0x74, 0x2c, 0x65, 0x29, 0x7b, 0x7a, 0x5b, 0x6e, 0x5d, 0x3d, 0x7a, 0x5b, 0x6e, 0x5d, 0x7c, 0x7c, 0x5b, 0x5d, 0x3b, 0x76, 0x61, 0x72, 0x20, 0x72, 0x3d, 0x6e, 0x65, 0x77, 0x20, 0x71, 0x28, 0x74, 0x2c, 0x65, 0x29, 0x3b, 0x63, 0x6f, 0x6e, 0x73, 0x6f, 0x6c, 0x65, 0x2e, 0x6c, 0x6f, 0x67, 0x28, 0x22, 0x50, 0x75, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x20, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x3a, 0x20, 0x22, 0x2b, 0x6e, 0x29, 0x2c, 0x7a, 0x5b, 0x6e, 0x5d, 0x2e, 0x70, 0x75, 0x73, 0x68, 0x28, 0x72, 0x29, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x4b, 0x28, 0x6e, 0x2c, 0x74, 0x29, 0x7b, 0x56, 0x28, 0x6e, 0x2c, 0x74, 0x29, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x51, 0x28, 0x6e, 0x2c, 0x74, 0x29, 0x7b, 0x56, 0x28, 0x6e, 0x2c, 0x74, 0x2c, 0x31, 0x29, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x58, 0x28, 0x6e, 0x29, 0x7b, 0x76, 0x61, 0x72, 0x20, 0x74, 0x3d, 0x6e, 0x2e, 0x6e, 0x61, 0x6d, 0x65, 0x3b, 0x69, 0x66, 0x28, 0x7a, 0x5b, 0x74, 0x5d, 0x29, 0x7b, 0x66, 0x6f, 0x72, 0x28, 0x76, 0x61, 0x72, 0x20, 0x65, 0x3d, 0x7a, 0x5b, 0x74, 0x5d, 0x2e, 0x73, 0x6c, 0x69, 0x63, 0x65, 0x28, 0x29, 0x2c, 0x72, 0x3d, 0x30, 0x3b, 0x72, 0x3c, 0x7a, 0x5b, 0x74, 0x5d, 0x2e, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x3b, 0x72, 0x2b, 0x3d, 0x31, 0x29, 0x7b, 0x76, 0x61, 0x72, 0x20, 0x69, 0x3d, 0x7a, 0x5b, 0x74, 0x5d, 0x5b, 0x72, 0x5d, 0x2c, 0x6f, 0x3d, 0x6e, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x3b, 0x69, 0x2e, 0x43, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x28, 0x6f, 0x29, 0x26, 0x26, 0x65, 0x2e, 0x73, 0x70, 0x6c, 0x69, 0x63, 0x65, 0x28, 0x72, 0x2c, 0x31, 0x29, 0x7d, 0x7a, 0x5b, 0x74, 0x5d, 0x3d, 0x65, 0x7d, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x59, 0x28, 0x6e, 0x29, 0x7b, 0x76, 0x61, 0x72, 0x20, 0x74, 0x3b, 0x74, 0x72, 0x79, 0x7b, 0x74, 0x3d, 0x4a, 0x53, 0x4f, 0x4e, 0x2e, 0x70, 0x61, 0x72, 0x73, 0x65, 0x28, 0x6e, 0x29, 0x7d, 0x63, 0x61, 0x74, 0x63, 0x68, 0x28, 0x74, 0x29, 0x7b, 0x74, 0x68, 0x72, 0x6f, 0x77, 0x20, 0x6e, 0x65, 0x77, 0x20, 0x67, 0x28, 0x22, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x20, 0x4a, 0x53, 0x4f, 0x4e, 0x20, 0x70, 0x61, 0x73, 0x73, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x3a, 0x20, 0x22, 0x2b, 0x6e, 0x29, 0x7d, 0x58, 0x28, 0x74, 0x29, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x5a, 0x28, 0x6e, 0x29, 0x7b, 0x76, 0x61, 0x72, 0x20, 0x74, 0x3d, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x3a, 0x6e, 0x2c, 0x64, 0x61, 0x74, 0x61, 0x3a, 0x5b, 0x5d, 0x2e, 0x73, 0x6c, 0x69, 0x63, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x6c, 0x79, 0x28, 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x29, 0x2e, 0x73, 0x6c, 0x69, 0x63, 0x65, 0x28, 0x31, 0x29, 0x7d, 0x3b, 0x58, 0x28, 0x74, 0x29, 0x2c, 0x64, 0x28, 0x22, 0x45, 0x6a, 0x22, 0x2b, 0x4a, 0x53, 0x4f, 0x4e, 0x2e, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x69, 0x66, 0x79, 0x28, 0x74, 0x29, 0x29, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x24, 0x28, 0x6e, 0x2c, 0x74, 0x29, 0x7b, 0x76, 0x61, 0x72, 0x20, 0x65, 0x3d, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x45, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x28, 0x22, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x22, 0x29, 0x3b, 0x65, 0x2e, 0x74, 0x65, 0x78, 0x74, 0x3d, 0x6e, 0x2c, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x62, 0x6f, 0x64, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x43, 0x68, 0x69, 0x6c, 0x64, 0x28, 0x65, 0x29, 0x2c, 0x74, 0x26, 0x26, 0x5a, 0x28, 0x74, 0x29, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6e, 0x6e, 0x28, 0x6e, 0x29, 0x7b, 0x74, 0x72, 0x79, 0x7b, 0x76, 0x61, 0x72, 0x20, 0x74, 0x3d, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x45, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x28, 0x22, 0x73, 0x74, 0x79, 0x6c, 0x65, 0x22, 0x29, 0x3b, 0x74, 0x2e, 0x73, 0x65, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x28, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x2c, 0x22, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x63, 0x73, 0x73, 0x22, 0x29, 0x2c, 0x74, 0x2e, 0x73, 0x74, 0x79, 0x6c, 0x65, 0x53, 0x68, 0x65, 0x65, 0x74, 0x3f, 0x74, 0x2e, 0x73, 0x74, 0x79, 0x6c, 0x65, 0x53, 0x68, 0x65, 0x65, 0x74, 0x2e, 0x63, 0x73, 0x73, 0x54, 0x65, 0x78, 0x74, 0x3d, 0x6e, 0x3a, 0x74, 0x2e, 0x61, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x43, 0x68, 0x69, 0x6c, 0x64, 0x28, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x65, 0x78, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x28, 0x6e, 0x29, 0x29, 0x2c, 0x28, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x7c, 0x7c, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x67, 0x65, 0x74, 0x45, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x42, 0x79, 0x54, 0x61, 0x67, 0x4e, 0x61, 0x6d, 0x65, 0x28, 0x22, 0x68, 0x65, 0x61, 0x64, 0x22, 0x29, 0x5b, 0x30, 0x5d, 0x29, 0x2e, 0x61, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x43, 0x68, 0x69, 0x6c, 0x64, 0x28, 0x74, 0x29, 0x7d, 0x63, 0x61, 0x74, 0x63, 0x68, 0x28, 0x6e, 0x29, 0x7b, 0x63, 0x6f, 0x6e, 0x73, 0x6f, 0x6c, 0x65, 0x2e, 0x6c, 0x6f, 0x67, 0x28, 0x6e, 0x29, 0x7d, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x74, 0x6e, 0x28, 0x29, 0x7b, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x57, 0x61, 0x69, 0x6c, 0x73, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x4d, 0x65, 0x6e, 0x75, 0x3d, 0x21, 0x30, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x65, 0x6e, 0x28, 0x6e, 0x2c, 0x74, 0x29, 0x7b, 0x76, 0x61, 0x72, 0x20, 0x65, 0x3b, 0x69, 0x66, 0x28, 0x21, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x77, 0x61, 0x69, 0x6c, 0x73, 0x29, 0x74, 0x68, 0x72, 0x6f, 0x77, 0x20, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x28, 0x22, 0x57, 0x61, 0x69, 0x6c, 0x73, 0x20, 0x69, 0x73, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x69, 0x73, 0x65, 0x64, 0x22, 0x29, 0x3b, 0x76, 0x61, 0x72, 0x20, 0x72, 0x3d, 0x5b, 0x5d, 0x3b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x77, 0x61, 0x69, 0x6c, 0x73, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x4f, 0x6e, 0x28, 0x22, 0x77, 0x61, 0x69, 0x6c, 0x73, 0x3a, 0x73, 0x79, 0x6e, 0x63, 0x3a, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x3a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x62, 0x79, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x3a, 0x22, 0x2b, 0x6e, 0x2c, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6e, 0x29, 0x7b, 0x76, 0x61, 0x72, 0x20, 0x74, 0x3d, 0x4a, 0x53, 0x4f, 0x4e, 0x2e, 0x70, 0x61, 0x72, 0x73, 0x65, 0x28, 0x6e, 0x29, 0x3b, 0x65, 0x3d, 0x74, 0x2c, 0x72, 0x2e, 0x66, 0x6f, 0x72, 0x45, 0x61, 0x63, 0x68, 0x28, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6e, 0x29, 0x7b, 0x6e, 0x28, 0x65, 0x29, 0x7d, 0x29, 0x29, 0x7d, 0x29, 0x29, 0x2c, 0x74, 0x26, 0x26, 0x74, 0x68, 0x69, 0x73, 0x2e, 0x73, 0x65, 0x74, 0x28, 0x74, 0x29, 0x2c, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x77, 0x61, 0x69, 0x6c, 0x73, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x45, 0x6d, 0x69, 0x74, 0x28, 0x22, 0x77, 0x61, 0x69, 0x6c, 0x73, 0x3a, 0x73, 0x79, 0x6e, 0x63, 0x3a, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x3a, 0x72, 0x65, 0x73, 0x79, 0x6e, 0x63, 0x3a, 0x22, 0x2b, 0x6e, 0x29, 0x2c, 0x7b, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x3a, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6e, 0x29, 0x7b, 0x72, 0x2e, 0x70, 0x75, 0x73, 0x68, 0x28, 0x6e, 0x29, 0x7d, 0x2c, 0x67, 0x65, 0x74, 0x3a, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x65, 0x7d, 0x2c, 0x73, 0x65, 0x74, 0x3a, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x74, 0x29, 0x7b, 0x65, 0x3d, 0x74, 0x2c, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x77, 0x61, 0x69, 0x6c, 0x73, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x45, 0x6d, 0x69, 0x74, 0x28, 0x22, 0x77, 0x61, 0x69, 0x6c, 0x73, 0x3a, 0x73, 0x79, 0x6e, 0x63, 0x3a, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x3a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x62, 0x79, 0x66, 0x72, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x64, 0x3a, 0x22, 0x2b, 0x6e, 0x2c, 0x4a, 0x53, 0x4f, 0x4e, 0x2e, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x69, 0x66, 0x79, 0x28, 0x65, 0x29, 0x29, 0x2c, 0x72, 0x2e, 0x66, 0x6f, 0x72, 0x45, 0x61, 0x63, 0x68, 0x28, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6e, 0x29, 0x7b, 0x6e, 0x28, 0x65, 0x29, 0x7d, 0x29, 0x29, 0x7d, 0x2c, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6e, 0x29, 0x7b, 0x76, 0x61, 0x72, 0x20, 0x74, 0x3d, 0x6e, 0x28, 0x65, 0x29, 0x3b, 0x74, 0x68, 0x69, 0x73, 0x2e, 0x73, 0x65, 0x74, 0x28, 0x74, 0x29, 0x7d, 0x7d, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x72, 0x6e, 0x28, 0x6e, 0x29, 0x7b, 0x64, 0x28, 0x22, 0x54, 0x49, 0x22, 0x2b, 0x6e, 0x29, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x28, 0x6f, 0x6e, 0x3d, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x61, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x7c, 0x7c, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6e, 0x29, 0x7b, 0x66, 0x6f, 0x72, 0x28, 0x76, 0x61, 0x72, 0x20, 0x74, 0x3d, 0x31, 0x3b, 0x74, 0x3c, 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x3b, 0x74, 0x2b, 0x2b, 0x29, 0x7b, 0x76, 0x61, 0x72, 0x20, 0x65, 0x3d, 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x5b, 0x74, 0x5d, 0x3b, 0x66, 0x6f, 0x72, 0x28, 0x76, 0x61, 0x72, 0x20, 0x72, 0x20, 0x69, 0x6e, 0x20, 0x65, 0x29, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x74, 0x79, 0x70, 0x65, 0x2e, 0x68, 0x61, 0x73, 0x4f, 0x77, 0x6e, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x2e, 0x63, 0x61, 0x6c, 0x6c, 0x28, 0x65, 0x2c, 0x72, 0x29, 0x26, 0x26, 0x28, 0x6e, 0x5b, 0x72, 0x5d, 0x3d, 0x65, 0x5b, 0x72, 0x5d, 0x29, 0x7d, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6e, 0x7d, 0x29, 0x2e, 0x61, 0x70, 0x70, 0x6c, 0x79, 0x28, 0x74, 0x68, 0x69, 0x73, 0x2c, 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x29, 0x7d, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x3d, 0x7b, 0x7d, 0x2c, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x77, 0x61, 0x69, 0x6c, 0x73, 0x3d, 0x7b, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x3a, 0x6c, 0x2c, 0x4c, 0x6f, 0x67, 0x3a, 0x72, 0x2c, 0x42, 0x72, 0x6f, 0x77, 0x73, 0x65, 0x72, 0x3a, 0x69, 0x2c, 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x3a, 0x6f, 0x2c, 0x54, 0x72, 0x61, 0x79, 0x3a, 0x63, 0x2c, 0x44, 0x69, 0x61, 0x6c, 0x6f, 0x67, 0x3a, 0x61, 0x2c, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x3a, 0x7b, 0x4f, 0x6e, 0x3a, 0x4b, 0x2c, 0x4f, 0x6e, 0x63, 0x65, 0x3a, 0x51, 0x2c, 0x4f, 0x6e, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x3a, 0x56, 0x2c, 0x45, 0x6d, 0x69, 0x74, 0x3a, 0x5a, 0x7d, 0x2c, 0x5f, 0x3a, 0x7b, 0x43, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x3a, 0x57, 0x2c, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x3a, 0x59, 0x2c, 0x41, 0x64, 0x64, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x3a, 0x24, 0x2c, 0x49, 0x6e, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x53, 0x53, 0x3a, 0x6e, 0x6e, 0x2c, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x4d, 0x65, 0x6e, 0x75, 0x3a, 0x74, 0x6e, 0x2c, 0x41, 0x64, 0x64, 0x49, 0x50, 0x43, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x3a, 0x66, 0x2c, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x43, 0x61, 0x6c, 0x6c, 0x3a, 0x78, 0x2c, 0x53, 0x65, 0x6e, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x3a, 0x64, 0x7d, 0x2c, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x3a, 0x75, 0x7d, 0x2c, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x77, 0x61, 0x69, 0x6c, 0x73, 0x2e, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x3d, 0x7b, 0x49, 0x73, 0x44, 0x61, 0x72, 0x6b, 0x4d, 0x6f, 0x64, 0x65, 0x3a, 0x65, 0x6e, 0x28, 0x22, 0x77, 0x61, 0x69, 0x6c, 0x73, 0x3a, 0x69, 0x73, 0x64, 0x61, 0x72, 0x6b, 0x6d, 0x6f, 0x64, 0x65, 0x22, 0x29, 0x2c, 0x4c, 0x6f, 0x67, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x3a, 0x65, 0x6e, 0x28, 0x22, 0x77, 0x61, 0x69, 0x6c, 0x73, 0x3a, 0x6c, 0x6f, 0x67, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x22, 0x29, 0x2c, 0x41, 0x70, 0x70, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x3a, 0x65, 0x6e, 0x28, 0x22, 0x77, 0x61, 0x69, 0x6c, 0x73, 0x3a, 0x61, 0x70, 0x70, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x22, 0x29, 0x7d, 0x2c, 0x6f, 0x6e, 0x28, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x77, 0x61, 0x69, 0x6c, 0x73, 0x2e, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x2c, 0x6c, 0x29, 0x2c, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x61, 0x64, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x28, 0x22, 0x6d, 0x6f, 0x75, 0x73, 0x65, 0x64, 0x6f, 0x77, 0x6e, 0x22, 0x2c, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6e, 0x29, 0x7b, 0x66, 0x6f, 0x72, 0x28, 0x76, 0x61, 0x72, 0x20, 0x74, 0x3d, 0x6e, 0x2e, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x3b, 0x6e, 0x75, 0x6c, 0x6c, 0x21, 0x3d, 0x74, 0x26, 0x26, 0x21, 0x74, 0x2e, 0x68, 0x61, 0x73, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x28, 0x22, 0x64, 0x61, 0x74, 0x61, 0x2d, 0x77, 0x61, 0x69, 0x6c, 0x73, 0x2d, 0x6e, 0x6f, 0x2d, 0x64, 0x72, 0x61, 0x67, 0x22, 0x29, 0x3b, 0x29, 0x7b, 0x69, 0x66, 0x28, 0x74, 0x2e, 0x68, 0x61, 0x73, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x28, 0x22, 0x64, 0x61, 0x74, 0x61, 0x2d, 0x77, 0x61, 0x69, 0x6c, 0x73, 0x2d, 0x64, 0x72, 0x61, 0x67, 0x22, 0x29, 0x29, 0x7b, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x77, 0x61, 0x69, 0x6c, 0x73, 0x44, 0x72, 0x61, 0x67, 0x28, 0x6e, 0x75, 0x6c, 0x6c, 0x29, 0x3b, 0x62, 0x72, 0x65, 0x61, 0x6b, 0x7d, 0x74, 0x3d, 0x74, 0x2e, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x45, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x7d, 0x7d, 0x29, 0x29, 0x2c, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x61, 0x64, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x28, 0x22, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x6d, 0x65, 0x6e, 0x75, 0x22, 0x2c, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6e, 0x29, 0x7b, 0x66, 0x6f, 0x72, 0x28, 0x76, 0x61, 0x72, 0x20, 0x74, 0x2c, 0x65, 0x3d, 0x6e, 0x2e, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x3b, 0x6e, 0x75, 0x6c, 0x6c, 0x21, 0x3d, 0x65, 0x26, 0x26, 0x6e, 0x75, 0x6c, 0x6c, 0x3d, 0x3d, 0x28, 0x74, 0x3d, 0x65, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x73, 0x65, 0x74, 0x5b, 0x22, 0x77, 0x61, 0x69, 0x6c, 0x73, 0x2d, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x2d, 0x6d, 0x65, 0x6e, 0x75, 0x2d, 0x69, 0x64, 0x22, 0x5d, 0x29, 0x3b, 0x29, 0x65, 0x3d, 0x65, 0x2e, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x45, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x3b, 0x69, 0x66, 0x28, 0x28, 0x6e, 0x75, 0x6c, 0x6c, 0x21, 0x3d, 0x74, 0x7c, 0x7c, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x57, 0x61, 0x69, 0x6c, 0x73, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x4d, 0x65, 0x6e, 0x75, 0x29, 0x26, 0x26, 0x6e, 0x2e, 0x70, 0x72, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x28, 0x29, 0x2c, 0x6e, 0x75, 0x6c, 0x6c, 0x21, 0x3d, 0x74, 0x29, 0x7b, 0x76, 0x61, 0x72, 0x20, 0x72, 0x3d, 0x7b, 0x69, 0x64, 0x3a, 0x74, 0x2c, 0x64, 0x61, 0x74, 0x61, 0x3a, 0x65, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x73, 0x65, 0x74, 0x5b, 0x22, 0x77, 0x61, 0x69, 0x6c, 0x73, 0x2d, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x2d, 0x6d, 0x65, 0x6e, 0x75, 0x2d, 0x64, 0x61, 0x74, 0x61, 0x22, 0x5d, 0x7c, 0x7c, 0x22, 0x22, 0x7d, 0x3b, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x77, 0x61, 0x69, 0x6c, 0x73, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x4d, 0x65, 0x6e, 0x75, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x28, 0x4a, 0x53, 0x4f, 0x4e, 0x2e, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x69, 0x66, 0x79, 0x28, 0x72, 0x29, 0x29, 0x7d, 0x7d, 0x29, 0x29, 0x2c, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x77, 0x61, 0x69, 0x6c, 0x73, 0x62, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x73, 0x26, 0x26, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6e, 0x29, 0x7b, 0x74, 0x72, 0x79, 0x7b, 0x6e, 0x3d, 0x4a, 0x53, 0x4f, 0x4e, 0x2e, 0x70, 0x61, 0x72, 0x73, 0x65, 0x28, 0x6e, 0x29, 0x7d, 0x63, 0x61, 0x74, 0x63, 0x68, 0x28, 0x6e, 0x29, 0x7b, 0x63, 0x6f, 0x6e, 0x73, 0x6f, 0x6c, 0x65, 0x2e, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x28, 0x6e, 0x29, 0x7d, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x3d, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x7c, 0x7c, 0x7b, 0x7d, 0x2c, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x6b, 0x65, 0x79, 0x73, 0x28, 0x6e, 0x29, 0x2e, 0x66, 0x6f, 0x72, 0x45, 0x61, 0x63, 0x68, 0x28, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x74, 0x29, 0x7b, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x5b, 0x74, 0x5d, 0x3d, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x5b, 0x74, 0x5d, 0x7c, 0x7c, 0x7b, 0x7d, 0x2c, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x6b, 0x65, 0x79, 0x73, 0x28, 0x6e, 0x5b, 0x74, 0x5d, 0x29, 0x2e, 0x66, 0x6f, 0x72, 0x45, 0x61, 0x63, 0x68, 0x28, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x65, 0x29, 0x7b, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x5b, 0x74, 0x5d, 0x5b, 0x65, 0x5d, 0x3d, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x5b, 0x74, 0x5d, 0x5b, 0x65, 0x5d, 0x7c, 0x7c, 0x7b, 0x7d, 0x2c, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x6b, 0x65, 0x79, 0x73, 0x28, 0x6e, 0x5b, 0x74, 0x5d, 0x5b, 0x65, 0x5d, 0x29, 0x2e, 0x66, 0x6f, 0x72, 0x45, 0x61, 0x63, 0x68, 0x28, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6e, 0x29, 0x7b, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x5b, 0x74, 0x5d, 0x5b, 0x65, 0x5d, 0x5b, 0x6e, 0x5d, 0x3d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x76, 0x61, 0x72, 0x20, 0x72, 0x3d, 0x30, 0x3b, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x69, 0x28, 0x29, 0x7b, 0x76, 0x61, 0x72, 0x20, 0x69, 0x3d, 0x5b, 0x5d, 0x2e, 0x73, 0x6c, 0x69, 0x63, 0x65, 0x2e, 0x63, 0x61, 0x6c, 0x6c, 0x28, 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x29, 0x3b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x43, 0x28, 0x5b, 0x74, 0x2c, 0x65, 0x2c, 0x6e, 0x5d, 0x2e, 0x6a, 0x6f, 0x69, 0x6e, 0x28, 0x22, 0x2e, 0x22, 0x29, 0x2c, 0x69, 0x2c, 0x72, 0x29, 0x7d, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x69, 0x2e, 0x73, 0x65, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x3d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6e, 0x29, 0x7b, 0x72, 0x3d, 0x6e, 0x7d, 0x2c, 0x69, 0x2e, 0x67, 0x65, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x3d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x72, 0x7d, 0x2c, 0x69, 0x7d, 0x28, 0x29, 0x7d, 0x29, 0x29, 0x7d, 0x29, 0x29, 0x7d, 0x29, 0x29, 0x7d, 0x28, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x77, 0x61, 0x69, 0x6c, 0x73, 0x62, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x73, 0x29, 0x2c, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x77, 0x61, 0x69, 0x6c, 0x73, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x45, 0x6d, 0x69, 0x74, 0x28, 0x22, 0x77, 0x61, 0x69, 0x6c, 0x73, 0x3a, 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x64, 0x22, 0x29, 0x7d, 0x5d, 0x29, 0x3b, 0x00};
\ No newline at end of file
diff --git a/v2/internal/ffenestri/runtime_windows.c b/v2/internal/ffenestri/runtime_windows.c
new file mode 100644
index 000000000..e9a3ff705
--- /dev/null
+++ b/v2/internal/ffenestri/runtime_windows.c
@@ -0,0 +1,5 @@
+
+// runtime.c (c) 2019-Present Lea Anthony.
+// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
+// This file was auto-generated. DO NOT MODIFY.
+const unsigned char runtime[]={0x76, 0x61, 0x72, 0x20, 0x57, 0x61, 0x69, 0x6c, 0x73, 0x3d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6e, 0x29, 0x7b, 0x76, 0x61, 0x72, 0x20, 0x74, 0x3d, 0x7b, 0x7d, 0x3b, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x65, 0x28, 0x72, 0x29, 0x7b, 0x69, 0x66, 0x28, 0x74, 0x5b, 0x72, 0x5d, 0x29, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x74, 0x5b, 0x72, 0x5d, 0x2e, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x73, 0x3b, 0x76, 0x61, 0x72, 0x20, 0x69, 0x3d, 0x74, 0x5b, 0x72, 0x5d, 0x3d, 0x7b, 0x69, 0x3a, 0x72, 0x2c, 0x6c, 0x3a, 0x21, 0x31, 0x2c, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x73, 0x3a, 0x7b, 0x7d, 0x7d, 0x3b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6e, 0x5b, 0x72, 0x5d, 0x2e, 0x63, 0x61, 0x6c, 0x6c, 0x28, 0x69, 0x2e, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x73, 0x2c, 0x69, 0x2c, 0x69, 0x2e, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x73, 0x2c, 0x65, 0x29, 0x2c, 0x69, 0x2e, 0x6c, 0x3d, 0x21, 0x30, 0x2c, 0x69, 0x2e, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x73, 0x7d, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x65, 0x2e, 0x6d, 0x3d, 0x6e, 0x2c, 0x65, 0x2e, 0x63, 0x3d, 0x74, 0x2c, 0x65, 0x2e, 0x64, 0x3d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6e, 0x2c, 0x74, 0x2c, 0x72, 0x29, 0x7b, 0x65, 0x2e, 0x6f, 0x28, 0x6e, 0x2c, 0x74, 0x29, 0x7c, 0x7c, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x28, 0x6e, 0x2c, 0x74, 0x2c, 0x7b, 0x65, 0x6e, 0x75, 0x6d, 0x65, 0x72, 0x61, 0x62, 0x6c, 0x65, 0x3a, 0x21, 0x30, 0x2c, 0x67, 0x65, 0x74, 0x3a, 0x72, 0x7d, 0x29, 0x7d, 0x2c, 0x65, 0x2e, 0x72, 0x3d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6e, 0x29, 0x7b, 0x22, 0x75, 0x6e, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, 0x22, 0x21, 0x3d, 0x74, 0x79, 0x70, 0x65, 0x6f, 0x66, 0x20, 0x53, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x26, 0x26, 0x53, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x2e, 0x74, 0x6f, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x54, 0x61, 0x67, 0x26, 0x26, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x28, 0x6e, 0x2c, 0x53, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x2e, 0x74, 0x6f, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x54, 0x61, 0x67, 0x2c, 0x7b, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x22, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x22, 0x7d, 0x29, 0x2c, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x28, 0x6e, 0x2c, 0x22, 0x5f, 0x5f, 0x65, 0x73, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x22, 0x2c, 0x7b, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x21, 0x30, 0x7d, 0x29, 0x7d, 0x2c, 0x65, 0x2e, 0x74, 0x3d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6e, 0x2c, 0x74, 0x29, 0x7b, 0x69, 0x66, 0x28, 0x31, 0x26, 0x74, 0x26, 0x26, 0x28, 0x6e, 0x3d, 0x65, 0x28, 0x6e, 0x29, 0x29, 0x2c, 0x38, 0x26, 0x74, 0x29, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6e, 0x3b, 0x69, 0x66, 0x28, 0x34, 0x26, 0x74, 0x26, 0x26, 0x22, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x22, 0x3d, 0x3d, 0x74, 0x79, 0x70, 0x65, 0x6f, 0x66, 0x20, 0x6e, 0x26, 0x26, 0x6e, 0x26, 0x26, 0x6e, 0x2e, 0x5f, 0x5f, 0x65, 0x73, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x29, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6e, 0x3b, 0x76, 0x61, 0x72, 0x20, 0x72, 0x3d, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x28, 0x6e, 0x75, 0x6c, 0x6c, 0x29, 0x3b, 0x69, 0x66, 0x28, 0x65, 0x2e, 0x72, 0x28, 0x72, 0x29, 0x2c, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x28, 0x72, 0x2c, 0x22, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x22, 0x2c, 0x7b, 0x65, 0x6e, 0x75, 0x6d, 0x65, 0x72, 0x61, 0x62, 0x6c, 0x65, 0x3a, 0x21, 0x30, 0x2c, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x6e, 0x7d, 0x29, 0x2c, 0x32, 0x26, 0x74, 0x26, 0x26, 0x22, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x22, 0x21, 0x3d, 0x74, 0x79, 0x70, 0x65, 0x6f, 0x66, 0x20, 0x6e, 0x29, 0x66, 0x6f, 0x72, 0x28, 0x76, 0x61, 0x72, 0x20, 0x69, 0x20, 0x69, 0x6e, 0x20, 0x6e, 0x29, 0x65, 0x2e, 0x64, 0x28, 0x72, 0x2c, 0x69, 0x2c, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x74, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6e, 0x5b, 0x74, 0x5d, 0x7d, 0x2e, 0x62, 0x69, 0x6e, 0x64, 0x28, 0x6e, 0x75, 0x6c, 0x6c, 0x2c, 0x69, 0x29, 0x29, 0x3b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x72, 0x7d, 0x2c, 0x65, 0x2e, 0x6e, 0x3d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6e, 0x29, 0x7b, 0x76, 0x61, 0x72, 0x20, 0x74, 0x3d, 0x6e, 0x26, 0x26, 0x6e, 0x2e, 0x5f, 0x5f, 0x65, 0x73, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x3f, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6e, 0x2e, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x7d, 0x3a, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6e, 0x7d, 0x3b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x65, 0x2e, 0x64, 0x28, 0x74, 0x2c, 0x22, 0x61, 0x22, 0x2c, 0x74, 0x29, 0x2c, 0x74, 0x7d, 0x2c, 0x65, 0x2e, 0x6f, 0x3d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6e, 0x2c, 0x74, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x74, 0x79, 0x70, 0x65, 0x2e, 0x68, 0x61, 0x73, 0x4f, 0x77, 0x6e, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x2e, 0x63, 0x61, 0x6c, 0x6c, 0x28, 0x6e, 0x2c, 0x74, 0x29, 0x7d, 0x2c, 0x65, 0x2e, 0x70, 0x3d, 0x22, 0x22, 0x2c, 0x65, 0x28, 0x65, 0x2e, 0x73, 0x3d, 0x30, 0x29, 0x7d, 0x28, 0x5b, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6e, 0x2c, 0x74, 0x2c, 0x65, 0x29, 0x7b, 0x22, 0x75, 0x73, 0x65, 0x20, 0x73, 0x74, 0x72, 0x69, 0x63, 0x74, 0x22, 0x3b, 0x65, 0x2e, 0x72, 0x28, 0x74, 0x29, 0x3b, 0x76, 0x61, 0x72, 0x20, 0x72, 0x3d, 0x7b, 0x7d, 0x3b, 0x65, 0x2e, 0x72, 0x28, 0x72, 0x29, 0x2c, 0x65, 0x2e, 0x64, 0x28, 0x72, 0x2c, 0x22, 0x54, 0x72, 0x61, 0x63, 0x65, 0x22, 0x2c, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x76, 0x7d, 0x29, 0x29, 0x2c, 0x65, 0x2e, 0x64, 0x28, 0x72, 0x2c, 0x22, 0x50, 0x72, 0x69, 0x6e, 0x74, 0x22, 0x2c, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x70, 0x7d, 0x29, 0x29, 0x2c, 0x65, 0x2e, 0x64, 0x28, 0x72, 0x2c, 0x22, 0x44, 0x65, 0x62, 0x75, 0x67, 0x22, 0x2c, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x79, 0x7d, 0x29, 0x29, 0x2c, 0x65, 0x2e, 0x64, 0x28, 0x72, 0x2c, 0x22, 0x49, 0x6e, 0x66, 0x6f, 0x22, 0x2c, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6d, 0x7d, 0x29, 0x29, 0x2c, 0x65, 0x2e, 0x64, 0x28, 0x72, 0x2c, 0x22, 0x57, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x22, 0x2c, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x62, 0x7d, 0x29, 0x29, 0x2c, 0x65, 0x2e, 0x64, 0x28, 0x72, 0x2c, 0x22, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x2c, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x67, 0x7d, 0x29, 0x29, 0x2c, 0x65, 0x2e, 0x64, 0x28, 0x72, 0x2c, 0x22, 0x46, 0x61, 0x74, 0x61, 0x6c, 0x22, 0x2c, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x68, 0x7d, 0x29, 0x29, 0x2c, 0x65, 0x2e, 0x64, 0x28, 0x72, 0x2c, 0x22, 0x53, 0x65, 0x74, 0x4c, 0x6f, 0x67, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x22, 0x2c, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x53, 0x7d, 0x29, 0x29, 0x2c, 0x65, 0x2e, 0x64, 0x28, 0x72, 0x2c, 0x22, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x22, 0x2c, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x45, 0x7d, 0x29, 0x29, 0x3b, 0x76, 0x61, 0x72, 0x20, 0x69, 0x3d, 0x7b, 0x7d, 0x3b, 0x65, 0x2e, 0x72, 0x28, 0x69, 0x29, 0x2c, 0x65, 0x2e, 0x64, 0x28, 0x69, 0x2c, 0x22, 0x4f, 0x70, 0x65, 0x6e, 0x22, 0x2c, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x54, 0x7d, 0x29, 0x29, 0x3b, 0x76, 0x61, 0x72, 0x20, 0x6f, 0x3d, 0x7b, 0x7d, 0x3b, 0x65, 0x2e, 0x72, 0x28, 0x6f, 0x29, 0x2c, 0x65, 0x2e, 0x64, 0x28, 0x6f, 0x2c, 0x22, 0x43, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x22, 0x2c, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6a, 0x7d, 0x29, 0x29, 0x2c, 0x65, 0x2e, 0x64, 0x28, 0x6f, 0x2c, 0x22, 0x53, 0x65, 0x74, 0x54, 0x69, 0x74, 0x6c, 0x65, 0x22, 0x2c, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x78, 0x7d, 0x29, 0x29, 0x2c, 0x65, 0x2e, 0x64, 0x28, 0x6f, 0x2c, 0x22, 0x46, 0x75, 0x6c, 0x6c, 0x73, 0x63, 0x72, 0x65, 0x65, 0x6e, 0x22, 0x2c, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x4d, 0x7d, 0x29, 0x29, 0x2c, 0x65, 0x2e, 0x64, 0x28, 0x6f, 0x2c, 0x22, 0x55, 0x6e, 0x46, 0x75, 0x6c, 0x6c, 0x73, 0x63, 0x72, 0x65, 0x65, 0x6e, 0x22, 0x2c, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x49, 0x7d, 0x29, 0x29, 0x2c, 0x65, 0x2e, 0x64, 0x28, 0x6f, 0x2c, 0x22, 0x53, 0x65, 0x74, 0x53, 0x69, 0x7a, 0x65, 0x22, 0x2c, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x44, 0x7d, 0x29, 0x29, 0x2c, 0x65, 0x2e, 0x64, 0x28, 0x6f, 0x2c, 0x22, 0x53, 0x65, 0x74, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x2c, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x50, 0x7d, 0x29, 0x29, 0x2c, 0x65, 0x2e, 0x64, 0x28, 0x6f, 0x2c, 0x22, 0x48, 0x69, 0x64, 0x65, 0x22, 0x2c, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x41, 0x7d, 0x29, 0x29, 0x2c, 0x65, 0x2e, 0x64, 0x28, 0x6f, 0x2c, 0x22, 0x53, 0x68, 0x6f, 0x77, 0x22, 0x2c, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x4a, 0x7d, 0x29, 0x29, 0x2c, 0x65, 0x2e, 0x64, 0x28, 0x6f, 0x2c, 0x22, 0x4d, 0x61, 0x78, 0x69, 0x6d, 0x69, 0x73, 0x65, 0x22, 0x2c, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x4c, 0x7d, 0x29, 0x29, 0x2c, 0x65, 0x2e, 0x64, 0x28, 0x6f, 0x2c, 0x22, 0x55, 0x6e, 0x6d, 0x61, 0x78, 0x69, 0x6d, 0x69, 0x73, 0x65, 0x22, 0x2c, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x52, 0x7d, 0x29, 0x29, 0x2c, 0x65, 0x2e, 0x64, 0x28, 0x6f, 0x2c, 0x22, 0x4d, 0x69, 0x6e, 0x69, 0x6d, 0x69, 0x73, 0x65, 0x22, 0x2c, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x5f, 0x7d, 0x29, 0x29, 0x2c, 0x65, 0x2e, 0x64, 0x28, 0x6f, 0x2c, 0x22, 0x55, 0x6e, 0x6d, 0x69, 0x6e, 0x69, 0x6d, 0x69, 0x73, 0x65, 0x22, 0x2c, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x46, 0x7d, 0x29, 0x29, 0x2c, 0x65, 0x2e, 0x64, 0x28, 0x6f, 0x2c, 0x22, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x22, 0x2c, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x55, 0x7d, 0x29, 0x29, 0x3b, 0x76, 0x61, 0x72, 0x20, 0x61, 0x3d, 0x7b, 0x7d, 0x3b, 0x65, 0x2e, 0x72, 0x28, 0x61, 0x29, 0x2c, 0x65, 0x2e, 0x64, 0x28, 0x61, 0x2c, 0x22, 0x4f, 0x70, 0x65, 0x6e, 0x22, 0x2c, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x42, 0x7d, 0x29, 0x29, 0x2c, 0x65, 0x2e, 0x64, 0x28, 0x61, 0x2c, 0x22, 0x53, 0x61, 0x76, 0x65, 0x22, 0x2c, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x48, 0x7d, 0x29, 0x29, 0x2c, 0x65, 0x2e, 0x64, 0x28, 0x61, 0x2c, 0x22, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x2c, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x47, 0x7d, 0x29, 0x29, 0x3b, 0x76, 0x61, 0x72, 0x20, 0x75, 0x3d, 0x7b, 0x7d, 0x3b, 0x65, 0x2e, 0x72, 0x28, 0x75, 0x29, 0x2c, 0x65, 0x2e, 0x64, 0x28, 0x75, 0x2c, 0x22, 0x4e, 0x65, 0x77, 0x22, 0x2c, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x65, 0x6e, 0x7d, 0x29, 0x29, 0x3b, 0x76, 0x61, 0x72, 0x20, 0x63, 0x3d, 0x7b, 0x7d, 0x3b, 0x65, 0x2e, 0x72, 0x28, 0x63, 0x29, 0x2c, 0x65, 0x2e, 0x64, 0x28, 0x63, 0x2c, 0x22, 0x53, 0x65, 0x74, 0x49, 0x63, 0x6f, 0x6e, 0x22, 0x2c, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x72, 0x6e, 0x7d, 0x29, 0x29, 0x3b, 0x76, 0x61, 0x72, 0x20, 0x6c, 0x3d, 0x7b, 0x41, 0x70, 0x70, 0x54, 0x79, 0x70, 0x65, 0x3a, 0x22, 0x64, 0x65, 0x73, 0x6b, 0x74, 0x6f, 0x70, 0x22, 0x2c, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x3a, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x22, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x73, 0x22, 0x7d, 0x7d, 0x3b, 0x76, 0x61, 0x72, 0x20, 0x73, 0x3d, 0x5b, 0x5d, 0x3b, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x66, 0x28, 0x6e, 0x29, 0x7b, 0x73, 0x2e, 0x70, 0x75, 0x73, 0x68, 0x28, 0x6e, 0x29, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x64, 0x28, 0x6e, 0x29, 0x7b, 0x69, 0x66, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6e, 0x29, 0x7b, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x77, 0x61, 0x69, 0x6c, 0x73, 0x49, 0x6e, 0x76, 0x6f, 0x6b, 0x65, 0x28, 0x6e, 0x29, 0x7d, 0x28, 0x6e, 0x29, 0x2c, 0x73, 0x2e, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x3e, 0x30, 0x29, 0x66, 0x6f, 0x72, 0x28, 0x76, 0x61, 0x72, 0x20, 0x74, 0x3d, 0x30, 0x3b, 0x74, 0x3c, 0x73, 0x2e, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x3b, 0x74, 0x2b, 0x2b, 0x29, 0x73, 0x5b, 0x74, 0x5d, 0x28, 0x6e, 0x29, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x77, 0x28, 0x6e, 0x2c, 0x74, 0x29, 0x7b, 0x64, 0x28, 0x22, 0x4c, 0x22, 0x2b, 0x6e, 0x2b, 0x74, 0x29, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x76, 0x28, 0x6e, 0x29, 0x7b, 0x77, 0x28, 0x22, 0x54, 0x22, 0x2c, 0x6e, 0x29, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x70, 0x28, 0x6e, 0x29, 0x7b, 0x77, 0x28, 0x22, 0x50, 0x22, 0x2c, 0x6e, 0x29, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x79, 0x28, 0x6e, 0x29, 0x7b, 0x77, 0x28, 0x22, 0x44, 0x22, 0x2c, 0x6e, 0x29, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6d, 0x28, 0x6e, 0x29, 0x7b, 0x77, 0x28, 0x22, 0x49, 0x22, 0x2c, 0x6e, 0x29, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x62, 0x28, 0x6e, 0x29, 0x7b, 0x77, 0x28, 0x22, 0x57, 0x22, 0x2c, 0x6e, 0x29, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x67, 0x28, 0x6e, 0x29, 0x7b, 0x77, 0x28, 0x22, 0x45, 0x22, 0x2c, 0x6e, 0x29, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x68, 0x28, 0x6e, 0x29, 0x7b, 0x77, 0x28, 0x22, 0x46, 0x22, 0x2c, 0x6e, 0x29, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x53, 0x28, 0x6e, 0x29, 0x7b, 0x77, 0x28, 0x22, 0x53, 0x22, 0x2c, 0x6e, 0x29, 0x7d, 0x76, 0x61, 0x72, 0x20, 0x4f, 0x2c, 0x45, 0x3d, 0x7b, 0x54, 0x52, 0x41, 0x43, 0x45, 0x3a, 0x31, 0x2c, 0x44, 0x45, 0x42, 0x55, 0x47, 0x3a, 0x32, 0x2c, 0x49, 0x4e, 0x46, 0x4f, 0x3a, 0x33, 0x2c, 0x57, 0x41, 0x52, 0x4e, 0x49, 0x4e, 0x47, 0x3a, 0x34, 0x2c, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x3a, 0x35, 0x7d, 0x2c, 0x6b, 0x3d, 0x7b, 0x7d, 0x3b, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x43, 0x28, 0x6e, 0x2c, 0x74, 0x2c, 0x65, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6e, 0x75, 0x6c, 0x6c, 0x21, 0x3d, 0x65, 0x26, 0x26, 0x6e, 0x75, 0x6c, 0x6c, 0x21, 0x3d, 0x65, 0x7c, 0x7c, 0x28, 0x65, 0x3d, 0x30, 0x29, 0x2c, 0x6e, 0x65, 0x77, 0x20, 0x50, 0x72, 0x6f, 0x6d, 0x69, 0x73, 0x65, 0x28, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x72, 0x2c, 0x69, 0x29, 0x7b, 0x76, 0x61, 0x72, 0x20, 0x6f, 0x3b, 0x64, 0x6f, 0x7b, 0x6f, 0x3d, 0x6e, 0x2b, 0x22, 0x2d, 0x22, 0x2b, 0x4f, 0x28, 0x29, 0x7d, 0x77, 0x68, 0x69, 0x6c, 0x65, 0x28, 0x6b, 0x5b, 0x6f, 0x5d, 0x29, 0x3b, 0x69, 0x66, 0x28, 0x65, 0x3e, 0x30, 0x29, 0x76, 0x61, 0x72, 0x20, 0x61, 0x3d, 0x73, 0x65, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x28, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x69, 0x28, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x28, 0x22, 0x43, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x6f, 0x20, 0x22, 0x2b, 0x6e, 0x2b, 0x22, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x64, 0x20, 0x6f, 0x75, 0x74, 0x2e, 0x20, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x20, 0x49, 0x44, 0x3a, 0x20, 0x22, 0x2b, 0x6f, 0x29, 0x29, 0x7d, 0x29, 0x2c, 0x65, 0x29, 0x3b, 0x6b, 0x5b, 0x6f, 0x5d, 0x3d, 0x7b, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x3a, 0x61, 0x2c, 0x72, 0x65, 0x6a, 0x65, 0x63, 0x74, 0x3a, 0x69, 0x2c, 0x72, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x3a, 0x72, 0x7d, 0x3b, 0x74, 0x72, 0x79, 0x7b, 0x76, 0x61, 0x72, 0x20, 0x75, 0x3d, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x3a, 0x6e, 0x2c, 0x61, 0x72, 0x67, 0x73, 0x3a, 0x74, 0x2c, 0x63, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x49, 0x44, 0x3a, 0x6f, 0x7d, 0x3b, 0x64, 0x28, 0x22, 0x43, 0x22, 0x2b, 0x4a, 0x53, 0x4f, 0x4e, 0x2e, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x69, 0x66, 0x79, 0x28, 0x75, 0x29, 0x29, 0x7d, 0x63, 0x61, 0x74, 0x63, 0x68, 0x28, 0x6e, 0x29, 0x7b, 0x63, 0x6f, 0x6e, 0x73, 0x6f, 0x6c, 0x65, 0x2e, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x28, 0x6e, 0x29, 0x7d, 0x7d, 0x29, 0x29, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x57, 0x28, 0x6e, 0x29, 0x7b, 0x76, 0x61, 0x72, 0x20, 0x74, 0x3b, 0x74, 0x72, 0x79, 0x7b, 0x74, 0x3d, 0x4a, 0x53, 0x4f, 0x4e, 0x2e, 0x70, 0x61, 0x72, 0x73, 0x65, 0x28, 0x6e, 0x29, 0x7d, 0x63, 0x61, 0x74, 0x63, 0x68, 0x28, 0x74, 0x29, 0x7b, 0x76, 0x61, 0x72, 0x20, 0x65, 0x3d, 0x22, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x20, 0x4a, 0x53, 0x4f, 0x4e, 0x20, 0x70, 0x61, 0x73, 0x73, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x3a, 0x20, 0x22, 0x2e, 0x63, 0x6f, 0x6e, 0x63, 0x61, 0x74, 0x28, 0x74, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2c, 0x22, 0x2e, 0x20, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x3a, 0x20, 0x22, 0x29, 0x2e, 0x63, 0x6f, 0x6e, 0x63, 0x61, 0x74, 0x28, 0x6e, 0x29, 0x3b, 0x74, 0x68, 0x72, 0x6f, 0x77, 0x20, 0x79, 0x28, 0x65, 0x29, 0x2c, 0x6e, 0x65, 0x77, 0x20, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x28, 0x65, 0x29, 0x7d, 0x76, 0x61, 0x72, 0x20, 0x72, 0x3d, 0x74, 0x2e, 0x63, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x69, 0x64, 0x2c, 0x69, 0x3d, 0x6b, 0x5b, 0x72, 0x5d, 0x3b, 0x69, 0x66, 0x28, 0x21, 0x69, 0x29, 0x7b, 0x76, 0x61, 0x72, 0x20, 0x6f, 0x3d, 0x22, 0x43, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x20, 0x27, 0x22, 0x2e, 0x63, 0x6f, 0x6e, 0x63, 0x61, 0x74, 0x28, 0x72, 0x2c, 0x22, 0x27, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x21, 0x21, 0x21, 0x22, 0x29, 0x3b, 0x74, 0x68, 0x72, 0x6f, 0x77, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x6f, 0x6c, 0x65, 0x2e, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x28, 0x6f, 0x29, 0x2c, 0x6e, 0x65, 0x77, 0x20, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x28, 0x6f, 0x29, 0x7d, 0x63, 0x6c, 0x65, 0x61, 0x72, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x28, 0x69, 0x2e, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x29, 0x2c, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x20, 0x6b, 0x5b, 0x72, 0x5d, 0x2c, 0x74, 0x2e, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x3f, 0x69, 0x2e, 0x72, 0x65, 0x6a, 0x65, 0x63, 0x74, 0x28, 0x74, 0x2e, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x29, 0x3a, 0x69, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x28, 0x74, 0x2e, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x29, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x4e, 0x28, 0x6e, 0x29, 0x7b, 0x76, 0x61, 0x72, 0x20, 0x74, 0x3d, 0x5b, 0x5d, 0x2e, 0x73, 0x6c, 0x69, 0x63, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x6c, 0x79, 0x28, 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x29, 0x2e, 0x73, 0x6c, 0x69, 0x63, 0x65, 0x28, 0x31, 0x29, 0x3b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x43, 0x28, 0x22, 0x2e, 0x77, 0x61, 0x69, 0x6c, 0x73, 0x2e, 0x22, 0x2b, 0x6e, 0x2c, 0x74, 0x29, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x54, 0x28, 0x6e, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x64, 0x28, 0x22, 0x52, 0x42, 0x4f, 0x22, 0x2b, 0x6e, 0x29, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6a, 0x28, 0x29, 0x7b, 0x64, 0x28, 0x22, 0x57, 0x63, 0x22, 0x29, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x78, 0x28, 0x6e, 0x29, 0x7b, 0x64, 0x28, 0x22, 0x57, 0x54, 0x22, 0x2b, 0x6e, 0x29, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x4d, 0x28, 0x29, 0x7b, 0x64, 0x28, 0x22, 0x57, 0x46, 0x22, 0x29, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x49, 0x28, 0x29, 0x7b, 0x64, 0x28, 0x22, 0x57, 0x66, 0x22, 0x29, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x44, 0x28, 0x6e, 0x2c, 0x74, 0x29, 0x7b, 0x64, 0x28, 0x22, 0x57, 0x73, 0x3a, 0x22, 0x2b, 0x6e, 0x2b, 0x22, 0x3a, 0x22, 0x2b, 0x74, 0x29, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x50, 0x28, 0x6e, 0x2c, 0x74, 0x29, 0x7b, 0x64, 0x28, 0x22, 0x57, 0x70, 0x3a, 0x22, 0x2b, 0x6e, 0x2b, 0x22, 0x3a, 0x22, 0x2b, 0x74, 0x29, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x28, 0x29, 0x7b, 0x64, 0x28, 0x22, 0x57, 0x48, 0x22, 0x29, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x4a, 0x28, 0x29, 0x7b, 0x64, 0x28, 0x22, 0x57, 0x53, 0x22, 0x29, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x4c, 0x28, 0x29, 0x7b, 0x64, 0x28, 0x22, 0x57, 0x4d, 0x22, 0x29, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x52, 0x28, 0x29, 0x7b, 0x64, 0x28, 0x22, 0x57, 0x55, 0x22, 0x29, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x5f, 0x28, 0x29, 0x7b, 0x64, 0x28, 0x22, 0x57, 0x6d, 0x22, 0x29, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x46, 0x28, 0x29, 0x7b, 0x64, 0x28, 0x22, 0x57, 0x75, 0x22, 0x29, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x55, 0x28, 0x29, 0x7b, 0x64, 0x28, 0x22, 0x57, 0x43, 0x22, 0x29, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x42, 0x28, 0x6e, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x4e, 0x28, 0x22, 0x44, 0x69, 0x61, 0x6c, 0x6f, 0x67, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x22, 0x2c, 0x6e, 0x29, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x48, 0x28, 0x6e, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x4e, 0x28, 0x22, 0x44, 0x69, 0x61, 0x6c, 0x6f, 0x67, 0x2e, 0x53, 0x61, 0x76, 0x65, 0x22, 0x2c, 0x6e, 0x29, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x47, 0x28, 0x6e, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x4e, 0x28, 0x22, 0x44, 0x69, 0x61, 0x6c, 0x6f, 0x67, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x2c, 0x6e, 0x29, 0x7d, 0x4f, 0x3d, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x3f, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x76, 0x61, 0x72, 0x20, 0x6e, 0x3d, 0x6e, 0x65, 0x77, 0x20, 0x55, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x41, 0x72, 0x72, 0x61, 0x79, 0x28, 0x31, 0x29, 0x3b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x67, 0x65, 0x74, 0x52, 0x61, 0x6e, 0x64, 0x6f, 0x6d, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x28, 0x6e, 0x29, 0x5b, 0x30, 0x5d, 0x7d, 0x3a, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x39, 0x30, 0x30, 0x37, 0x31, 0x39, 0x39, 0x32, 0x35, 0x34, 0x37, 0x34, 0x30, 0x39, 0x39, 0x31, 0x2a, 0x4d, 0x61, 0x74, 0x68, 0x2e, 0x72, 0x61, 0x6e, 0x64, 0x6f, 0x6d, 0x28, 0x29, 0x7d, 0x2c, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x3d, 0x7b, 0x7d, 0x3b, 0x76, 0x61, 0x72, 0x20, 0x71, 0x3d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6e, 0x28, 0x74, 0x2c, 0x65, 0x29, 0x7b, 0x21, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6e, 0x2c, 0x74, 0x29, 0x7b, 0x69, 0x66, 0x28, 0x21, 0x28, 0x6e, 0x20, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x6f, 0x66, 0x20, 0x74, 0x29, 0x29, 0x74, 0x68, 0x72, 0x6f, 0x77, 0x20, 0x6e, 0x65, 0x77, 0x20, 0x54, 0x79, 0x70, 0x65, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x28, 0x22, 0x43, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x20, 0x61, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x20, 0x61, 0x73, 0x20, 0x61, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x29, 0x7d, 0x28, 0x74, 0x68, 0x69, 0x73, 0x2c, 0x6e, 0x29, 0x2c, 0x65, 0x3d, 0x65, 0x7c, 0x7c, 0x2d, 0x31, 0x2c, 0x74, 0x68, 0x69, 0x73, 0x2e, 0x43, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x3d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6e, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x74, 0x2e, 0x61, 0x70, 0x70, 0x6c, 0x79, 0x28, 0x6e, 0x75, 0x6c, 0x6c, 0x2c, 0x6e, 0x29, 0x2c, 0x2d, 0x31, 0x21, 0x3d, 0x3d, 0x65, 0x26, 0x26, 0x30, 0x3d, 0x3d, 0x3d, 0x28, 0x65, 0x2d, 0x3d, 0x31, 0x29, 0x7d, 0x7d, 0x2c, 0x7a, 0x3d, 0x7b, 0x7d, 0x3b, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x56, 0x28, 0x6e, 0x2c, 0x74, 0x2c, 0x65, 0x29, 0x7b, 0x7a, 0x5b, 0x6e, 0x5d, 0x3d, 0x7a, 0x5b, 0x6e, 0x5d, 0x7c, 0x7c, 0x5b, 0x5d, 0x3b, 0x76, 0x61, 0x72, 0x20, 0x72, 0x3d, 0x6e, 0x65, 0x77, 0x20, 0x71, 0x28, 0x74, 0x2c, 0x65, 0x29, 0x3b, 0x63, 0x6f, 0x6e, 0x73, 0x6f, 0x6c, 0x65, 0x2e, 0x6c, 0x6f, 0x67, 0x28, 0x22, 0x50, 0x75, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x20, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x3a, 0x20, 0x22, 0x2b, 0x6e, 0x29, 0x2c, 0x7a, 0x5b, 0x6e, 0x5d, 0x2e, 0x70, 0x75, 0x73, 0x68, 0x28, 0x72, 0x29, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x4b, 0x28, 0x6e, 0x2c, 0x74, 0x29, 0x7b, 0x56, 0x28, 0x6e, 0x2c, 0x74, 0x29, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x51, 0x28, 0x6e, 0x2c, 0x74, 0x29, 0x7b, 0x56, 0x28, 0x6e, 0x2c, 0x74, 0x2c, 0x31, 0x29, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x58, 0x28, 0x6e, 0x29, 0x7b, 0x76, 0x61, 0x72, 0x20, 0x74, 0x3d, 0x6e, 0x2e, 0x6e, 0x61, 0x6d, 0x65, 0x3b, 0x69, 0x66, 0x28, 0x7a, 0x5b, 0x74, 0x5d, 0x29, 0x7b, 0x66, 0x6f, 0x72, 0x28, 0x76, 0x61, 0x72, 0x20, 0x65, 0x3d, 0x7a, 0x5b, 0x74, 0x5d, 0x2e, 0x73, 0x6c, 0x69, 0x63, 0x65, 0x28, 0x29, 0x2c, 0x72, 0x3d, 0x30, 0x3b, 0x72, 0x3c, 0x7a, 0x5b, 0x74, 0x5d, 0x2e, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x3b, 0x72, 0x2b, 0x3d, 0x31, 0x29, 0x7b, 0x76, 0x61, 0x72, 0x20, 0x69, 0x3d, 0x7a, 0x5b, 0x74, 0x5d, 0x5b, 0x72, 0x5d, 0x2c, 0x6f, 0x3d, 0x6e, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x3b, 0x69, 0x2e, 0x43, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x28, 0x6f, 0x29, 0x26, 0x26, 0x65, 0x2e, 0x73, 0x70, 0x6c, 0x69, 0x63, 0x65, 0x28, 0x72, 0x2c, 0x31, 0x29, 0x7d, 0x7a, 0x5b, 0x74, 0x5d, 0x3d, 0x65, 0x7d, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x59, 0x28, 0x6e, 0x29, 0x7b, 0x76, 0x61, 0x72, 0x20, 0x74, 0x3b, 0x74, 0x72, 0x79, 0x7b, 0x74, 0x3d, 0x4a, 0x53, 0x4f, 0x4e, 0x2e, 0x70, 0x61, 0x72, 0x73, 0x65, 0x28, 0x6e, 0x29, 0x7d, 0x63, 0x61, 0x74, 0x63, 0x68, 0x28, 0x74, 0x29, 0x7b, 0x74, 0x68, 0x72, 0x6f, 0x77, 0x20, 0x6e, 0x65, 0x77, 0x20, 0x67, 0x28, 0x22, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x20, 0x4a, 0x53, 0x4f, 0x4e, 0x20, 0x70, 0x61, 0x73, 0x73, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x3a, 0x20, 0x22, 0x2b, 0x6e, 0x29, 0x7d, 0x58, 0x28, 0x74, 0x29, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x5a, 0x28, 0x6e, 0x29, 0x7b, 0x76, 0x61, 0x72, 0x20, 0x74, 0x3d, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x3a, 0x6e, 0x2c, 0x64, 0x61, 0x74, 0x61, 0x3a, 0x5b, 0x5d, 0x2e, 0x73, 0x6c, 0x69, 0x63, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x6c, 0x79, 0x28, 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x29, 0x2e, 0x73, 0x6c, 0x69, 0x63, 0x65, 0x28, 0x31, 0x29, 0x7d, 0x3b, 0x58, 0x28, 0x74, 0x29, 0x2c, 0x64, 0x28, 0x22, 0x45, 0x6a, 0x22, 0x2b, 0x4a, 0x53, 0x4f, 0x4e, 0x2e, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x69, 0x66, 0x79, 0x28, 0x74, 0x29, 0x29, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x24, 0x28, 0x6e, 0x2c, 0x74, 0x29, 0x7b, 0x76, 0x61, 0x72, 0x20, 0x65, 0x3d, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x45, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x28, 0x22, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x22, 0x29, 0x3b, 0x65, 0x2e, 0x74, 0x65, 0x78, 0x74, 0x3d, 0x6e, 0x2c, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x62, 0x6f, 0x64, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x43, 0x68, 0x69, 0x6c, 0x64, 0x28, 0x65, 0x29, 0x2c, 0x74, 0x26, 0x26, 0x5a, 0x28, 0x74, 0x29, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6e, 0x6e, 0x28, 0x6e, 0x29, 0x7b, 0x74, 0x72, 0x79, 0x7b, 0x76, 0x61, 0x72, 0x20, 0x74, 0x3d, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x45, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x28, 0x22, 0x73, 0x74, 0x79, 0x6c, 0x65, 0x22, 0x29, 0x3b, 0x74, 0x2e, 0x73, 0x65, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x28, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x2c, 0x22, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x63, 0x73, 0x73, 0x22, 0x29, 0x2c, 0x74, 0x2e, 0x73, 0x74, 0x79, 0x6c, 0x65, 0x53, 0x68, 0x65, 0x65, 0x74, 0x3f, 0x74, 0x2e, 0x73, 0x74, 0x79, 0x6c, 0x65, 0x53, 0x68, 0x65, 0x65, 0x74, 0x2e, 0x63, 0x73, 0x73, 0x54, 0x65, 0x78, 0x74, 0x3d, 0x6e, 0x3a, 0x74, 0x2e, 0x61, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x43, 0x68, 0x69, 0x6c, 0x64, 0x28, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x65, 0x78, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x28, 0x6e, 0x29, 0x29, 0x2c, 0x28, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x7c, 0x7c, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x67, 0x65, 0x74, 0x45, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x42, 0x79, 0x54, 0x61, 0x67, 0x4e, 0x61, 0x6d, 0x65, 0x28, 0x22, 0x68, 0x65, 0x61, 0x64, 0x22, 0x29, 0x5b, 0x30, 0x5d, 0x29, 0x2e, 0x61, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x43, 0x68, 0x69, 0x6c, 0x64, 0x28, 0x74, 0x29, 0x7d, 0x63, 0x61, 0x74, 0x63, 0x68, 0x28, 0x6e, 0x29, 0x7b, 0x63, 0x6f, 0x6e, 0x73, 0x6f, 0x6c, 0x65, 0x2e, 0x6c, 0x6f, 0x67, 0x28, 0x6e, 0x29, 0x7d, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x74, 0x6e, 0x28, 0x29, 0x7b, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x57, 0x61, 0x69, 0x6c, 0x73, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x4d, 0x65, 0x6e, 0x75, 0x3d, 0x21, 0x30, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x65, 0x6e, 0x28, 0x6e, 0x2c, 0x74, 0x29, 0x7b, 0x76, 0x61, 0x72, 0x20, 0x65, 0x3b, 0x69, 0x66, 0x28, 0x21, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x77, 0x61, 0x69, 0x6c, 0x73, 0x29, 0x74, 0x68, 0x72, 0x6f, 0x77, 0x20, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x28, 0x22, 0x57, 0x61, 0x69, 0x6c, 0x73, 0x20, 0x69, 0x73, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x69, 0x73, 0x65, 0x64, 0x22, 0x29, 0x3b, 0x76, 0x61, 0x72, 0x20, 0x72, 0x3d, 0x5b, 0x5d, 0x3b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x77, 0x61, 0x69, 0x6c, 0x73, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x4f, 0x6e, 0x28, 0x22, 0x77, 0x61, 0x69, 0x6c, 0x73, 0x3a, 0x73, 0x79, 0x6e, 0x63, 0x3a, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x3a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x62, 0x79, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x3a, 0x22, 0x2b, 0x6e, 0x2c, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6e, 0x29, 0x7b, 0x76, 0x61, 0x72, 0x20, 0x74, 0x3d, 0x4a, 0x53, 0x4f, 0x4e, 0x2e, 0x70, 0x61, 0x72, 0x73, 0x65, 0x28, 0x6e, 0x29, 0x3b, 0x65, 0x3d, 0x74, 0x2c, 0x72, 0x2e, 0x66, 0x6f, 0x72, 0x45, 0x61, 0x63, 0x68, 0x28, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6e, 0x29, 0x7b, 0x6e, 0x28, 0x65, 0x29, 0x7d, 0x29, 0x29, 0x7d, 0x29, 0x29, 0x2c, 0x74, 0x26, 0x26, 0x74, 0x68, 0x69, 0x73, 0x2e, 0x73, 0x65, 0x74, 0x28, 0x74, 0x29, 0x2c, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x77, 0x61, 0x69, 0x6c, 0x73, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x45, 0x6d, 0x69, 0x74, 0x28, 0x22, 0x77, 0x61, 0x69, 0x6c, 0x73, 0x3a, 0x73, 0x79, 0x6e, 0x63, 0x3a, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x3a, 0x72, 0x65, 0x73, 0x79, 0x6e, 0x63, 0x3a, 0x22, 0x2b, 0x6e, 0x29, 0x2c, 0x7b, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x3a, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6e, 0x29, 0x7b, 0x72, 0x2e, 0x70, 0x75, 0x73, 0x68, 0x28, 0x6e, 0x29, 0x7d, 0x2c, 0x67, 0x65, 0x74, 0x3a, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x65, 0x7d, 0x2c, 0x73, 0x65, 0x74, 0x3a, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x74, 0x29, 0x7b, 0x65, 0x3d, 0x74, 0x2c, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x77, 0x61, 0x69, 0x6c, 0x73, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x45, 0x6d, 0x69, 0x74, 0x28, 0x22, 0x77, 0x61, 0x69, 0x6c, 0x73, 0x3a, 0x73, 0x79, 0x6e, 0x63, 0x3a, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x3a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x62, 0x79, 0x66, 0x72, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x64, 0x3a, 0x22, 0x2b, 0x6e, 0x2c, 0x4a, 0x53, 0x4f, 0x4e, 0x2e, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x69, 0x66, 0x79, 0x28, 0x65, 0x29, 0x29, 0x2c, 0x72, 0x2e, 0x66, 0x6f, 0x72, 0x45, 0x61, 0x63, 0x68, 0x28, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6e, 0x29, 0x7b, 0x6e, 0x28, 0x65, 0x29, 0x7d, 0x29, 0x29, 0x7d, 0x2c, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6e, 0x29, 0x7b, 0x76, 0x61, 0x72, 0x20, 0x74, 0x3d, 0x6e, 0x28, 0x65, 0x29, 0x3b, 0x74, 0x68, 0x69, 0x73, 0x2e, 0x73, 0x65, 0x74, 0x28, 0x74, 0x29, 0x7d, 0x7d, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x72, 0x6e, 0x28, 0x6e, 0x29, 0x7b, 0x64, 0x28, 0x22, 0x54, 0x49, 0x22, 0x2b, 0x6e, 0x29, 0x7d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x28, 0x6f, 0x6e, 0x3d, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x61, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x7c, 0x7c, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6e, 0x29, 0x7b, 0x66, 0x6f, 0x72, 0x28, 0x76, 0x61, 0x72, 0x20, 0x74, 0x3d, 0x31, 0x3b, 0x74, 0x3c, 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x3b, 0x74, 0x2b, 0x2b, 0x29, 0x7b, 0x76, 0x61, 0x72, 0x20, 0x65, 0x3d, 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x5b, 0x74, 0x5d, 0x3b, 0x66, 0x6f, 0x72, 0x28, 0x76, 0x61, 0x72, 0x20, 0x72, 0x20, 0x69, 0x6e, 0x20, 0x65, 0x29, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x74, 0x79, 0x70, 0x65, 0x2e, 0x68, 0x61, 0x73, 0x4f, 0x77, 0x6e, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x2e, 0x63, 0x61, 0x6c, 0x6c, 0x28, 0x65, 0x2c, 0x72, 0x29, 0x26, 0x26, 0x28, 0x6e, 0x5b, 0x72, 0x5d, 0x3d, 0x65, 0x5b, 0x72, 0x5d, 0x29, 0x7d, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6e, 0x7d, 0x29, 0x2e, 0x61, 0x70, 0x70, 0x6c, 0x79, 0x28, 0x74, 0x68, 0x69, 0x73, 0x2c, 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x29, 0x7d, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x3d, 0x7b, 0x7d, 0x2c, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x77, 0x61, 0x69, 0x6c, 0x73, 0x3d, 0x7b, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x3a, 0x6c, 0x2c, 0x4c, 0x6f, 0x67, 0x3a, 0x72, 0x2c, 0x42, 0x72, 0x6f, 0x77, 0x73, 0x65, 0x72, 0x3a, 0x69, 0x2c, 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x3a, 0x6f, 0x2c, 0x54, 0x72, 0x61, 0x79, 0x3a, 0x63, 0x2c, 0x44, 0x69, 0x61, 0x6c, 0x6f, 0x67, 0x3a, 0x61, 0x2c, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x3a, 0x7b, 0x4f, 0x6e, 0x3a, 0x4b, 0x2c, 0x4f, 0x6e, 0x63, 0x65, 0x3a, 0x51, 0x2c, 0x4f, 0x6e, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x3a, 0x56, 0x2c, 0x45, 0x6d, 0x69, 0x74, 0x3a, 0x5a, 0x7d, 0x2c, 0x5f, 0x3a, 0x7b, 0x43, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x3a, 0x57, 0x2c, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x3a, 0x59, 0x2c, 0x41, 0x64, 0x64, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x3a, 0x24, 0x2c, 0x49, 0x6e, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x53, 0x53, 0x3a, 0x6e, 0x6e, 0x2c, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x4d, 0x65, 0x6e, 0x75, 0x3a, 0x74, 0x6e, 0x2c, 0x41, 0x64, 0x64, 0x49, 0x50, 0x43, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x3a, 0x66, 0x2c, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x43, 0x61, 0x6c, 0x6c, 0x3a, 0x4e, 0x2c, 0x53, 0x65, 0x6e, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x3a, 0x64, 0x7d, 0x2c, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x3a, 0x75, 0x7d, 0x2c, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x77, 0x61, 0x69, 0x6c, 0x73, 0x2e, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x3d, 0x7b, 0x49, 0x73, 0x44, 0x61, 0x72, 0x6b, 0x4d, 0x6f, 0x64, 0x65, 0x3a, 0x65, 0x6e, 0x28, 0x22, 0x77, 0x61, 0x69, 0x6c, 0x73, 0x3a, 0x69, 0x73, 0x64, 0x61, 0x72, 0x6b, 0x6d, 0x6f, 0x64, 0x65, 0x22, 0x29, 0x2c, 0x4c, 0x6f, 0x67, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x3a, 0x65, 0x6e, 0x28, 0x22, 0x77, 0x61, 0x69, 0x6c, 0x73, 0x3a, 0x6c, 0x6f, 0x67, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x22, 0x29, 0x2c, 0x41, 0x70, 0x70, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x3a, 0x65, 0x6e, 0x28, 0x22, 0x77, 0x61, 0x69, 0x6c, 0x73, 0x3a, 0x61, 0x70, 0x70, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x22, 0x29, 0x7d, 0x2c, 0x6f, 0x6e, 0x28, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x77, 0x61, 0x69, 0x6c, 0x73, 0x2e, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x2c, 0x6c, 0x29, 0x2c, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x61, 0x64, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x28, 0x22, 0x6d, 0x6f, 0x75, 0x73, 0x65, 0x64, 0x6f, 0x77, 0x6e, 0x22, 0x2c, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6e, 0x29, 0x7b, 0x66, 0x6f, 0x72, 0x28, 0x76, 0x61, 0x72, 0x20, 0x74, 0x3d, 0x6e, 0x2e, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x3b, 0x6e, 0x75, 0x6c, 0x6c, 0x21, 0x3d, 0x74, 0x26, 0x26, 0x21, 0x74, 0x2e, 0x68, 0x61, 0x73, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x28, 0x22, 0x64, 0x61, 0x74, 0x61, 0x2d, 0x77, 0x61, 0x69, 0x6c, 0x73, 0x2d, 0x6e, 0x6f, 0x2d, 0x64, 0x72, 0x61, 0x67, 0x22, 0x29, 0x3b, 0x29, 0x7b, 0x69, 0x66, 0x28, 0x74, 0x2e, 0x68, 0x61, 0x73, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x28, 0x22, 0x64, 0x61, 0x74, 0x61, 0x2d, 0x77, 0x61, 0x69, 0x6c, 0x73, 0x2d, 0x64, 0x72, 0x61, 0x67, 0x22, 0x29, 0x29, 0x7b, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x77, 0x61, 0x69, 0x6c, 0x73, 0x49, 0x6e, 0x76, 0x6f, 0x6b, 0x65, 0x28, 0x22, 0x77, 0x61, 0x69, 0x6c, 0x73, 0x2d, 0x64, 0x72, 0x61, 0x67, 0x22, 0x29, 0x3b, 0x62, 0x72, 0x65, 0x61, 0x6b, 0x7d, 0x74, 0x3d, 0x74, 0x2e, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x45, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x7d, 0x7d, 0x29, 0x29, 0x2c, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x61, 0x64, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x28, 0x22, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x6d, 0x65, 0x6e, 0x75, 0x22, 0x2c, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6e, 0x29, 0x7b, 0x66, 0x6f, 0x72, 0x28, 0x76, 0x61, 0x72, 0x20, 0x74, 0x2c, 0x65, 0x3d, 0x6e, 0x2e, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x3b, 0x6e, 0x75, 0x6c, 0x6c, 0x21, 0x3d, 0x65, 0x26, 0x26, 0x6e, 0x75, 0x6c, 0x6c, 0x3d, 0x3d, 0x28, 0x74, 0x3d, 0x65, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x73, 0x65, 0x74, 0x5b, 0x22, 0x77, 0x61, 0x69, 0x6c, 0x73, 0x2d, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x2d, 0x6d, 0x65, 0x6e, 0x75, 0x2d, 0x69, 0x64, 0x22, 0x5d, 0x29, 0x3b, 0x29, 0x65, 0x3d, 0x65, 0x2e, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x45, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x3b, 0x69, 0x66, 0x28, 0x28, 0x6e, 0x75, 0x6c, 0x6c, 0x21, 0x3d, 0x74, 0x7c, 0x7c, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x57, 0x61, 0x69, 0x6c, 0x73, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x4d, 0x65, 0x6e, 0x75, 0x29, 0x26, 0x26, 0x6e, 0x2e, 0x70, 0x72, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x28, 0x29, 0x2c, 0x6e, 0x75, 0x6c, 0x6c, 0x21, 0x3d, 0x74, 0x29, 0x7b, 0x76, 0x61, 0x72, 0x20, 0x72, 0x3d, 0x7b, 0x69, 0x64, 0x3a, 0x74, 0x2c, 0x64, 0x61, 0x74, 0x61, 0x3a, 0x65, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x73, 0x65, 0x74, 0x5b, 0x22, 0x77, 0x61, 0x69, 0x6c, 0x73, 0x2d, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x2d, 0x6d, 0x65, 0x6e, 0x75, 0x2d, 0x64, 0x61, 0x74, 0x61, 0x22, 0x5d, 0x7c, 0x7c, 0x22, 0x22, 0x7d, 0x3b, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x77, 0x61, 0x69, 0x6c, 0x73, 0x49, 0x6e, 0x76, 0x6f, 0x6b, 0x65, 0x28, 0x22, 0x43, 0x22, 0x2b, 0x4a, 0x53, 0x4f, 0x4e, 0x2e, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x69, 0x66, 0x79, 0x28, 0x72, 0x29, 0x29, 0x7d, 0x7d, 0x29, 0x29, 0x2c, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x77, 0x61, 0x69, 0x6c, 0x73, 0x62, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x73, 0x26, 0x26, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6e, 0x29, 0x7b, 0x74, 0x72, 0x79, 0x7b, 0x6e, 0x3d, 0x4a, 0x53, 0x4f, 0x4e, 0x2e, 0x70, 0x61, 0x72, 0x73, 0x65, 0x28, 0x6e, 0x29, 0x7d, 0x63, 0x61, 0x74, 0x63, 0x68, 0x28, 0x6e, 0x29, 0x7b, 0x63, 0x6f, 0x6e, 0x73, 0x6f, 0x6c, 0x65, 0x2e, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x28, 0x6e, 0x29, 0x7d, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x3d, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x7c, 0x7c, 0x7b, 0x7d, 0x2c, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x6b, 0x65, 0x79, 0x73, 0x28, 0x6e, 0x29, 0x2e, 0x66, 0x6f, 0x72, 0x45, 0x61, 0x63, 0x68, 0x28, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x74, 0x29, 0x7b, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x5b, 0x74, 0x5d, 0x3d, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x5b, 0x74, 0x5d, 0x7c, 0x7c, 0x7b, 0x7d, 0x2c, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x6b, 0x65, 0x79, 0x73, 0x28, 0x6e, 0x5b, 0x74, 0x5d, 0x29, 0x2e, 0x66, 0x6f, 0x72, 0x45, 0x61, 0x63, 0x68, 0x28, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x65, 0x29, 0x7b, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x5b, 0x74, 0x5d, 0x5b, 0x65, 0x5d, 0x3d, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x5b, 0x74, 0x5d, 0x5b, 0x65, 0x5d, 0x7c, 0x7c, 0x7b, 0x7d, 0x2c, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x6b, 0x65, 0x79, 0x73, 0x28, 0x6e, 0x5b, 0x74, 0x5d, 0x5b, 0x65, 0x5d, 0x29, 0x2e, 0x66, 0x6f, 0x72, 0x45, 0x61, 0x63, 0x68, 0x28, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6e, 0x29, 0x7b, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x5b, 0x74, 0x5d, 0x5b, 0x65, 0x5d, 0x5b, 0x6e, 0x5d, 0x3d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x76, 0x61, 0x72, 0x20, 0x72, 0x3d, 0x30, 0x3b, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x69, 0x28, 0x29, 0x7b, 0x76, 0x61, 0x72, 0x20, 0x69, 0x3d, 0x5b, 0x5d, 0x2e, 0x73, 0x6c, 0x69, 0x63, 0x65, 0x2e, 0x63, 0x61, 0x6c, 0x6c, 0x28, 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x29, 0x3b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x43, 0x28, 0x5b, 0x74, 0x2c, 0x65, 0x2c, 0x6e, 0x5d, 0x2e, 0x6a, 0x6f, 0x69, 0x6e, 0x28, 0x22, 0x2e, 0x22, 0x29, 0x2c, 0x69, 0x2c, 0x72, 0x29, 0x7d, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x69, 0x2e, 0x73, 0x65, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x3d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6e, 0x29, 0x7b, 0x72, 0x3d, 0x6e, 0x7d, 0x2c, 0x69, 0x2e, 0x67, 0x65, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x3d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x72, 0x7d, 0x2c, 0x69, 0x7d, 0x28, 0x29, 0x7d, 0x29, 0x29, 0x7d, 0x29, 0x29, 0x7d, 0x29, 0x29, 0x7d, 0x28, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x77, 0x61, 0x69, 0x6c, 0x73, 0x62, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x73, 0x29, 0x2c, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x77, 0x61, 0x69, 0x6c, 0x73, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x45, 0x6d, 0x69, 0x74, 0x28, 0x22, 0x77, 0x61, 0x69, 0x6c, 0x73, 0x3a, 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x64, 0x22, 0x29, 0x7d, 0x5d, 0x29, 0x3b, 0x00};
\ No newline at end of file
diff --git a/v2/internal/ffenestri/traymenu_darwin.c b/v2/internal/ffenestri/traymenu_darwin.c
new file mode 100644
index 000000000..1854d838d
--- /dev/null
+++ b/v2/internal/ffenestri/traymenu_darwin.c
@@ -0,0 +1,266 @@
+//
+// Created by Lea Anthony on 12/1/21.
+//
+
+#include "common.h"
+#include "traymenu_darwin.h"
+#include "trayicons.h"
+
+extern Class trayMenuDelegateClass;
+
+// A cache for all our tray menu icons
+// Global because it's a singleton
+struct hashmap_s trayIconCache;
+
+TrayMenu* NewTrayMenu(const char* menuJSON) {
+ TrayMenu* result = malloc(sizeof(TrayMenu));
+
+/*
+ {"ID":"0","Label":"Test Tray Label","Icon":"","ProcessedMenu":{"Menu":{"Items":[{"ID":"0","Label":"Show Window","Type":"Text","Disabled":false,"Hidden":false,"Checked":false,"Foreground":0,"Background":0},{"ID":"1","Label":"Hide Window","Type":"Text","Disabled":false,"Hidden":false,"Checked":false,"Foreground":0,"Background":0},{"ID":"2","Label":"Minimise Window","Type":"Text","Disabled":false,"Hidden":false,"Checked":false,"Foreground":0,"Background":0},{"ID":"3","Label":"Unminimise Window","Type":"Text","Disabled":false,"Hidden":false,"Checked":false,"Foreground":0,"Background":0}]},"RadioGroups":null}}
+*/
+ JsonNode* processedJSON = json_decode(menuJSON);
+ if( processedJSON == NULL ) {
+ ABORT("[NewTrayMenu] Unable to parse TrayMenu JSON: %s", menuJSON);
+ }
+
+ // Save reference to this json
+ result->processedJSON = processedJSON;
+
+ // TODO: Make this configurable
+ result->trayIconPosition = NSImageLeft;
+
+ result->ID = mustJSONString(processedJSON, "ID");
+ result->label = mustJSONString(processedJSON, "Label");
+ result->icon = mustJSONString(processedJSON, "Image");
+ result->fontName = getJSONString(processedJSON, "FontName");
+ result->RGBA = getJSONString(processedJSON, "RGBA");
+ getJSONBool(processedJSON, "MacTemplateImage", &result->templateImage);
+ result->fontSize = 0;
+ getJSONInt(processedJSON, "FontSize", &result->fontSize);
+ result->tooltip = NULL;
+ result->tooltip = getJSONString(processedJSON, "Tooltip");
+ result->disabled = false;
+ getJSONBool(processedJSON, "Disabled", &result->disabled);
+
+ result->styledLabel = getJSONObject(processedJSON, "StyledLabel");
+
+ // Create the menu
+ JsonNode* processedMenu = mustJSONObject(processedJSON, "ProcessedMenu");
+ result->menu = NewMenu(processedMenu);
+
+ result->delegate = NULL;
+
+ // Init tray status bar item
+ result->statusbaritem = NULL;
+
+ // Set the menu type and store the tray ID in the parent data
+ result->menu->menuType = TrayMenuType;
+ result->menu->parentData = (void*) result->ID;
+
+ return result;
+}
+
+void DumpTrayMenu(TrayMenu* trayMenu) {
+ printf(" ['%s':%p] = { label: '%s', icon: '%s', menu: %p, statusbar: %p }\n", trayMenu->ID, trayMenu, trayMenu->label, trayMenu->icon, trayMenu->menu, trayMenu->statusbaritem );
+}
+
+
+void UpdateTrayLabel(TrayMenu *trayMenu, const char *label, const char *fontName, int fontSize, const char *RGBA, const char *tooltip, bool disabled, JsonNode *styledLabel) {
+
+ // Exit early if NULL
+ if( trayMenu->label == NULL ) {
+ return;
+ }
+ // Update button label
+ id statusBarButton = msg_reg(trayMenu->statusbaritem, s("button"));
+ id attributedString = NULL;
+ if( styledLabel != NULL) {
+ attributedString = createAttributedStringFromStyledLabel(styledLabel, fontName, fontSize);
+ } else {
+ attributedString = createAttributedString(label, fontName, fontSize, RGBA);
+ }
+
+ if( tooltip != NULL ) {
+ msg_id(statusBarButton, s("setToolTip:"), str(tooltip));
+ }
+
+ msg_bool(statusBarButton, s("setEnabled:"), !disabled);
+
+ msg_id(statusBarButton, s("setAttributedTitle:"), attributedString);
+}
+
+void UpdateTrayIcon(TrayMenu *trayMenu) {
+
+ // Exit early if NULL
+ if( trayMenu->icon == NULL ) {
+ return;
+ }
+
+ id statusBarButton = msg_reg(trayMenu->statusbaritem, s("button"));
+
+ // Empty icon means remove it
+ if( STREMPTY(trayMenu->icon) ) {
+ // Remove image
+ msg_id(statusBarButton, s("setImage:"), NULL);
+ return;
+ }
+
+ id trayImage = hashmap_get(&trayIconCache, trayMenu->icon, strlen(trayMenu->icon));
+
+ // If we don't have the image in the icon cache then assume it's base64 encoded image data
+ if (trayImage == NULL) {
+ trayImage = createImageFromBase64Data(trayMenu->icon, trayMenu->templateImage);
+ }
+
+ msg_int(statusBarButton, s("setImagePosition:"), trayMenu->trayIconPosition);
+ msg_id(statusBarButton, s("setImage:"), trayImage);
+
+}
+
+void ShowTrayMenu(TrayMenu* trayMenu) {
+
+ // Create a status bar item if we don't have one
+ if( trayMenu->statusbaritem == NULL ) {
+ id statusBar = msg_reg( c("NSStatusBar"), s("systemStatusBar") );
+ trayMenu->statusbaritem = ((id(*)(id, SEL, CGFloat))objc_msgSend)(statusBar, s("statusItemWithLength:"), NSVariableStatusItemLength);
+ msg_reg(trayMenu->statusbaritem, s("retain"));
+ }
+
+ id statusBarButton = msg_reg(trayMenu->statusbaritem, s("button"));
+ msg_uint(statusBarButton, s("setImagePosition:"), trayMenu->trayIconPosition);
+ // Update the icon if needed
+ UpdateTrayIcon(trayMenu);
+
+ // Update the label if needed
+ UpdateTrayLabel(trayMenu, trayMenu->label, trayMenu->fontName, trayMenu->fontSize, trayMenu->RGBA, trayMenu->tooltip, trayMenu->disabled, trayMenu->styledLabel);
+
+ // Update the menu
+ id menu = GetMenu(trayMenu->menu);
+ objc_setAssociatedObject(menu, "trayMenuID", str(trayMenu->ID), OBJC_ASSOCIATION_ASSIGN);
+
+ // Create delegate
+ id trayMenuDelegate = msg_reg((id)trayMenuDelegateClass, s("new"));
+ msg_id(menu, s("setDelegate:"), trayMenuDelegate);
+ objc_setAssociatedObject(trayMenuDelegate, "menu", menu, OBJC_ASSOCIATION_ASSIGN);
+
+ // Create menu delegate
+ trayMenu->delegate = trayMenuDelegate;
+
+ msg_id(trayMenu->statusbaritem, s("setMenu:"), menu);
+}
+
+// UpdateTrayMenuInPlace receives 2 menus. The current menu gets
+// updated with the data from the new menu.
+void UpdateTrayMenuInPlace(TrayMenu* currentMenu, TrayMenu* newMenu) {
+
+ // Delete the old menu
+ DeleteMenu(currentMenu->menu);
+ if( currentMenu->delegate != NULL ) {
+ msg_reg(currentMenu->delegate, s("release"));
+ currentMenu->delegate = NULL;
+ }
+
+ // Set the new one
+ currentMenu->menu = newMenu->menu;
+
+ // Delete the old JSON
+ json_delete(currentMenu->processedJSON);
+
+ // Set the new JSON
+ currentMenu->processedJSON = newMenu->processedJSON;
+
+ // Copy the other data
+ currentMenu->ID = newMenu->ID;
+ currentMenu->label = newMenu->label;
+ currentMenu->styledLabel = newMenu->styledLabel;
+ currentMenu->trayIconPosition = newMenu->trayIconPosition;
+ currentMenu->icon = newMenu->icon;
+
+}
+
+void DeleteTrayMenu(TrayMenu* trayMenu) {
+
+ // Delete the menu
+ DeleteMenu(trayMenu->menu);
+ if( trayMenu->delegate != NULL ) {
+ msg_reg(trayMenu->delegate, s("release"));
+ trayMenu->delegate = NULL;
+ }
+
+ // Free JSON
+ if (trayMenu->processedJSON != NULL ) {
+ json_delete(trayMenu->processedJSON);
+ }
+
+ // Free the status item
+ if ( trayMenu->statusbaritem != NULL ) {
+ id statusBar = msg_reg( c("NSStatusBar"), s("systemStatusBar") );
+ msg_id(statusBar, s("removeStatusItem:"), trayMenu->statusbaritem);
+ msg_reg(trayMenu->statusbaritem, s("release"));
+ trayMenu->statusbaritem = NULL;
+ }
+
+ // Free the tray menu memory
+ MEMFREE(trayMenu);
+}
+void DeleteTrayMenuKeepStatusBarItem(TrayMenu* trayMenu) {
+
+ // Delete the menu
+ DeleteMenu(trayMenu->menu);
+ if( trayMenu->delegate != NULL ) {
+ msg_reg(trayMenu->delegate, s("release"));
+ trayMenu->delegate = NULL;
+ }
+
+ // Free JSON
+ if (trayMenu->processedJSON != NULL ) {
+ json_delete(trayMenu->processedJSON);
+ }
+
+ // Free the tray menu memory
+ MEMFREE(trayMenu);
+}
+
+void LoadTrayIcons() {
+
+ // Allocate the Tray Icons
+ if( 0 != hashmap_create((const unsigned)4, &trayIconCache)) {
+ // Couldn't allocate map
+ ABORT("Not enough memory to allocate trayIconCache!");
+ }
+
+ unsigned int count = 0;
+ while( 1 ) {
+ const unsigned char *name = trayIcons[count++];
+ if( name == 0x00 ) {
+ break;
+ }
+ const unsigned char *lengthAsString = trayIcons[count++];
+ if( name == 0x00 ) {
+ break;
+ }
+ const unsigned char *data = trayIcons[count++];
+ if( data == 0x00 ) {
+ break;
+ }
+ int length = atoi((const char *)lengthAsString);
+
+ // Create the icon and add to the hashmap
+ id imageData = ((id(*)(id, SEL, id, int))objc_msgSend)(c("NSData"), s("dataWithBytes:length:"), (id)data, length);
+ id trayImage = ALLOC("NSImage");
+ msg_id(trayImage, s("initWithData:"), imageData);
+ hashmap_put(&trayIconCache, (const char *)name, strlen((const char *)name), trayImage);
+ }
+}
+
+void UnloadTrayIcons() {
+ // Release the tray cache images
+ if( hashmap_num_entries(&trayIconCache) > 0 ) {
+ if (0!=hashmap_iterate_pairs(&trayIconCache, releaseNSObject, NULL)) {
+ ABORT("failed to release hashmap entries!");
+ }
+ }
+
+ //Free radio groups hashmap
+ hashmap_destroy(&trayIconCache);
+}
\ No newline at end of file
diff --git a/v2/internal/ffenestri/traymenu_darwin.h b/v2/internal/ffenestri/traymenu_darwin.h
new file mode 100644
index 000000000..763b4d63d
--- /dev/null
+++ b/v2/internal/ffenestri/traymenu_darwin.h
@@ -0,0 +1,51 @@
+//
+// Created by Lea Anthony on 12/1/21.
+//
+
+#ifndef TRAYMENU_DARWIN_H
+#define TRAYMENU_DARWIN_H
+
+#include "common.h"
+#include "menu_darwin.h"
+
+typedef struct {
+
+ const char *label;
+ const char *icon;
+ const char *ID;
+ const char *tooltip;
+
+ bool templateImage;
+ const char *fontName;
+ int fontSize;
+ const char *RGBA;
+
+ bool disabled;
+
+ Menu* menu;
+
+ id statusbaritem;
+ unsigned int trayIconPosition;
+
+ JsonNode* processedJSON;
+
+ JsonNode* styledLabel;
+
+ id delegate;
+
+} TrayMenu;
+
+TrayMenu* NewTrayMenu(const char *trayJSON);
+void DumpTrayMenu(TrayMenu* trayMenu);
+void ShowTrayMenu(TrayMenu* trayMenu);
+void UpdateTrayMenuInPlace(TrayMenu* currentMenu, TrayMenu* newMenu);
+void UpdateTrayIcon(TrayMenu *trayMenu);
+void UpdateTrayLabel(TrayMenu *trayMenu, const char *label, const char *fontName, int fontSize, const char *RGBA, const char *tooltip, bool disabled, JsonNode *styledLabel);
+
+void LoadTrayIcons();
+void UnloadTrayIcons();
+
+void DeleteTrayMenu(TrayMenu* trayMenu);
+void DeleteTrayMenuKeepStatusBarItem(TrayMenu* trayMenu);
+
+#endif //TRAYMENU_DARWIN_H
diff --git a/v2/internal/ffenestri/traymenustore_darwin.c b/v2/internal/ffenestri/traymenustore_darwin.c
new file mode 100644
index 000000000..362c07bf7
--- /dev/null
+++ b/v2/internal/ffenestri/traymenustore_darwin.c
@@ -0,0 +1,173 @@
+//
+// Created by Lea Anthony on 12/1/21.
+//
+
+#include "common.h"
+#include "traymenustore_darwin.h"
+#include "traymenu_darwin.h"
+#include
+
+TrayMenuStore* NewTrayMenuStore() {
+
+ TrayMenuStore* result = malloc(sizeof(TrayMenuStore));
+
+ // Allocate Tray Menu Store
+ if( 0 != hashmap_create((const unsigned)4, &result->trayMenuMap)) {
+ ABORT("[NewTrayMenuStore] Not enough memory to allocate trayMenuMap!");
+ }
+
+ if (pthread_mutex_init(&result->lock, NULL) != 0) {
+ printf("\n mutex init has failed\n");
+ exit(1);
+ }
+
+ return result;
+}
+
+int dumpTrayMenu(void *const context, struct hashmap_element_s *const e) {
+ DumpTrayMenu(e->data);
+ return 0;
+}
+
+void DumpTrayMenuStore(TrayMenuStore* store) {
+ pthread_mutex_lock(&store->lock);
+ hashmap_iterate_pairs(&store->trayMenuMap, dumpTrayMenu, NULL);
+ pthread_mutex_unlock(&store->lock);
+}
+
+void AddTrayMenuToStore(TrayMenuStore* store, const char* menuJSON) {
+
+ TrayMenu* newMenu = NewTrayMenu(menuJSON);
+
+ pthread_mutex_lock(&store->lock);
+ //TODO: check if there is already an entry for this menu
+ hashmap_put(&store->trayMenuMap, newMenu->ID, strlen(newMenu->ID), newMenu);
+ pthread_mutex_unlock(&store->lock);
+}
+
+int showTrayMenu(void *const context, struct hashmap_element_s *const e) {
+ ShowTrayMenu(e->data);
+ // 0 to retain element, -1 to delete.
+ return 0;
+}
+
+void ShowTrayMenusInStore(TrayMenuStore* store) {
+ pthread_mutex_lock(&store->lock);
+ if( hashmap_num_entries(&store->trayMenuMap) > 0 ) {
+ hashmap_iterate_pairs(&store->trayMenuMap, showTrayMenu, NULL);
+ }
+ pthread_mutex_unlock(&store->lock);
+}
+
+int freeTrayMenu(void *const context, struct hashmap_element_s *const e) {
+ DeleteTrayMenu(e->data);
+ return -1;
+}
+
+void DeleteTrayMenuStore(TrayMenuStore *store) {
+
+ // Delete context menus
+ if (hashmap_num_entries(&store->trayMenuMap) > 0) {
+ if (0 != hashmap_iterate_pairs(&store->trayMenuMap, freeTrayMenu, NULL)) {
+ ABORT("[DeleteContextMenuStore] Failed to release contextMenuStore entries!");
+ }
+ }
+
+ // Destroy tray menu map
+ hashmap_destroy(&store->trayMenuMap);
+
+ pthread_mutex_destroy(&store->lock);
+}
+
+TrayMenu* GetTrayMenuFromStore(TrayMenuStore* store, const char* menuID) {
+ // Get the current menu
+ pthread_mutex_lock(&store->lock);
+ TrayMenu* result = hashmap_get(&store->trayMenuMap, menuID, strlen(menuID));
+ pthread_mutex_unlock(&store->lock);
+ return result;
+}
+
+TrayMenu* MustGetTrayMenuFromStore(TrayMenuStore* store, const char* menuID) {
+ // Get the current menu
+ pthread_mutex_lock(&store->lock);
+ TrayMenu* result = hashmap_get(&store->trayMenuMap, menuID, strlen(menuID));
+ pthread_mutex_unlock(&store->lock);
+
+ if (result == NULL ) {
+ ABORT("Unable to find TrayMenu with ID '%s' in the TrayMenuStore!", menuID);
+ }
+ return result;
+}
+
+void DeleteTrayMenuInStore(TrayMenuStore* store, const char* ID) {
+
+ TrayMenu *menu = MustGetTrayMenuFromStore(store, ID);
+ pthread_mutex_lock(&store->lock);
+ hashmap_remove(&store->trayMenuMap, ID, strlen(ID));
+ pthread_mutex_unlock(&store->lock);
+ DeleteTrayMenu(menu);
+}
+
+void UpdateTrayMenuLabelInStore(TrayMenuStore* store, const char* JSON) {
+ // Parse the JSON
+ JsonNode *parsedUpdate = mustParseJSON(JSON);
+
+ // Get the data out
+ const char* ID = mustJSONString(parsedUpdate, "ID");
+ const char* Label = mustJSONString(parsedUpdate, "Label");
+
+ // Check we have this menu
+ TrayMenu *menu = MustGetTrayMenuFromStore(store, ID);
+
+ const char *fontName = getJSONString(parsedUpdate, "FontName");
+ const char *RGBA = getJSONString(parsedUpdate, "RGBA");
+ int fontSize = 0;
+ getJSONInt(parsedUpdate, "FontSize", &fontSize);
+ const char *tooltip = getJSONString(parsedUpdate, "Tooltip");
+ bool disabled = false;
+ getJSONBool(parsedUpdate, "Disabled", &disabled);
+
+ JsonNode *styledLabel = getJSONObject(parsedUpdate, "StyledLabel");
+
+ UpdateTrayLabel(menu, Label, fontName, fontSize, RGBA, tooltip, disabled, styledLabel);
+
+ json_delete(parsedUpdate);
+}
+
+void UpdateTrayMenuInStore(TrayMenuStore* store, const char* menuJSON) {
+ TrayMenu* newMenu = NewTrayMenu(menuJSON);
+// DumpTrayMenu(newMenu);
+
+ // Get the current menu
+ TrayMenu *currentMenu = GetTrayMenuFromStore(store, newMenu->ID);
+
+ // If we don't have a menu, we create one
+ if ( currentMenu == NULL ) {
+ // Store the new menu
+ pthread_mutex_lock(&store->lock);
+ hashmap_put(&store->trayMenuMap, newMenu->ID, strlen(newMenu->ID), newMenu);
+ pthread_mutex_unlock(&store->lock);
+
+ // Show it
+ ShowTrayMenu(newMenu);
+ return;
+ }
+// DumpTrayMenu(currentMenu);
+
+ // Save the status bar reference
+ newMenu->statusbaritem = currentMenu->statusbaritem;
+
+ pthread_mutex_lock(&store->lock);
+ hashmap_remove(&store->trayMenuMap, newMenu->ID, strlen(newMenu->ID));
+ pthread_mutex_unlock(&store->lock);
+
+ // Delete the current menu
+ DeleteTrayMenuKeepStatusBarItem(currentMenu);
+
+ pthread_mutex_lock(&store->lock);
+ hashmap_put(&store->trayMenuMap, newMenu->ID, strlen(newMenu->ID), newMenu);
+ pthread_mutex_unlock(&store->lock);
+
+ // Show the updated menu
+ ShowTrayMenu(newMenu);
+}
diff --git a/v2/internal/ffenestri/traymenustore_darwin.h b/v2/internal/ffenestri/traymenustore_darwin.h
new file mode 100644
index 000000000..a09a9e004
--- /dev/null
+++ b/v2/internal/ffenestri/traymenustore_darwin.h
@@ -0,0 +1,36 @@
+//
+// Created by Lea Anthony on 7/1/21.
+//
+
+#ifndef TRAYMENUSTORE_DARWIN_H
+#define TRAYMENUSTORE_DARWIN_H
+
+#include "traymenu_darwin.h"
+
+#include
+
+typedef struct {
+
+ int dummy;
+
+ // This is our tray menu map
+ // It maps tray IDs to TrayMenu*
+ struct hashmap_s trayMenuMap;
+
+ pthread_mutex_t lock;
+
+} TrayMenuStore;
+
+TrayMenuStore* NewTrayMenuStore();
+
+void AddTrayMenuToStore(TrayMenuStore* store, const char* menuJSON);
+void UpdateTrayMenuInStore(TrayMenuStore* store, const char* menuJSON);
+void ShowTrayMenusInStore(TrayMenuStore* store);
+void DeleteTrayMenuStore(TrayMenuStore* store);
+
+TrayMenu* GetTrayMenuByID(TrayMenuStore* store, const char* menuID);
+
+void UpdateTrayMenuLabelInStore(TrayMenuStore* store, const char* JSON);
+void DeleteTrayMenuInStore(TrayMenuStore* store, const char* id);
+
+#endif //TRAYMENUSTORE_DARWIN_H
diff --git a/v2/internal/ffenestri/vec.c b/v2/internal/ffenestri/vec.c
new file mode 100644
index 000000000..6ab8bfa96
--- /dev/null
+++ b/v2/internal/ffenestri/vec.c
@@ -0,0 +1,115 @@
+// +build !windows
+
+/**
+ * Copyright (c) 2014 rxi
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MIT license. See LICENSE for details.
+ */
+
+#include "vec.h"
+
+
+int vec_expand_(char **data, int *length, int *capacity, int memsz) {
+ if (*length + 1 > *capacity) {
+ void *ptr;
+ int n = (*capacity == 0) ? 1 : *capacity << 1;
+ ptr = realloc(*data, n * memsz);
+ if (ptr == NULL) return -1;
+ *data = ptr;
+ *capacity = n;
+ }
+ return 0;
+}
+
+
+int vec_reserve_(char **data, int *length, int *capacity, int memsz, int n) {
+ (void) length;
+ if (n > *capacity) {
+ void *ptr = realloc(*data, n * memsz);
+ if (ptr == NULL) return -1;
+ *data = ptr;
+ *capacity = n;
+ }
+ return 0;
+}
+
+
+int vec_reserve_po2_(
+ char **data, int *length, int *capacity, int memsz, int n
+) {
+ int n2 = 1;
+ if (n == 0) return 0;
+ while (n2 < n) n2 <<= 1;
+ return vec_reserve_(data, length, capacity, memsz, n2);
+}
+
+
+int vec_compact_(char **data, int *length, int *capacity, int memsz) {
+ if (*length == 0) {
+ free(*data);
+ *data = NULL;
+ *capacity = 0;
+ return 0;
+ } else {
+ void *ptr;
+ int n = *length;
+ ptr = realloc(*data, n * memsz);
+ if (ptr == NULL) return -1;
+ *capacity = n;
+ *data = ptr;
+ }
+ return 0;
+}
+
+
+int vec_insert_(char **data, int *length, int *capacity, int memsz,
+ int idx
+) {
+ int err = vec_expand_(data, length, capacity, memsz);
+ if (err) return err;
+ memmove(*data + (idx + 1) * memsz,
+ *data + idx * memsz,
+ (*length - idx) * memsz);
+ return 0;
+}
+
+
+void vec_splice_(char **data, int *length, int *capacity, int memsz,
+ int start, int count
+) {
+ (void) capacity;
+ memmove(*data + start * memsz,
+ *data + (start + count) * memsz,
+ (*length - start - count) * memsz);
+}
+
+
+void vec_swapsplice_(char **data, int *length, int *capacity, int memsz,
+ int start, int count
+) {
+ (void) capacity;
+ memmove(*data + start * memsz,
+ *data + (*length - count) * memsz,
+ count * memsz);
+}
+
+
+void vec_swap_(char **data, int *length, int *capacity, int memsz,
+ int idx1, int idx2
+) {
+ unsigned char *a, *b, tmp;
+ int count;
+ (void) length;
+ (void) capacity;
+ if (idx1 == idx2) return;
+ a = (unsigned char*) *data + idx1 * memsz;
+ b = (unsigned char*) *data + idx2 * memsz;
+ count = memsz;
+ while (count--) {
+ tmp = *a;
+ *a = *b;
+ *b = tmp;
+ a++, b++;
+ }
+}
diff --git a/v2/internal/ffenestri/vec.h b/v2/internal/ffenestri/vec.h
new file mode 100644
index 000000000..19362c987
--- /dev/null
+++ b/v2/internal/ffenestri/vec.h
@@ -0,0 +1,181 @@
+/**
+ * Copyright (c) 2014 rxi
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MIT license. See LICENSE for details.
+ */
+
+#ifndef VEC_H
+#define VEC_H
+
+#include
+#include
+
+#define VEC_VERSION "0.2.1"
+
+
+#define vec_unpack_(v)\
+ (char**)&(v)->data, &(v)->length, &(v)->capacity, sizeof(*(v)->data)
+
+
+#define vec_t(T)\
+ struct { T *data; int length, capacity; }
+
+
+#define vec_init(v)\
+ memset((v), 0, sizeof(*(v)))
+
+
+#define vec_deinit(v)\
+ ( free((v)->data),\
+ vec_init(v) )
+
+
+#define vec_push(v, val)\
+ ( vec_expand_(vec_unpack_(v)) ? -1 :\
+ ((v)->data[(v)->length++] = (val), 0), 0 )
+
+
+#define vec_pop(v)\
+ (v)->data[--(v)->length]
+
+
+#define vec_splice(v, start, count)\
+ ( vec_splice_(vec_unpack_(v), start, count),\
+ (v)->length -= (count) )
+
+
+#define vec_swapsplice(v, start, count)\
+ ( vec_swapsplice_(vec_unpack_(v), start, count),\
+ (v)->length -= (count) )
+
+
+#define vec_insert(v, idx, val)\
+ ( vec_insert_(vec_unpack_(v), idx) ? -1 :\
+ ((v)->data[idx] = (val), 0), (v)->length++, 0 )
+
+
+#define vec_sort(v, fn)\
+ qsort((v)->data, (v)->length, sizeof(*(v)->data), fn)
+
+
+#define vec_swap(v, idx1, idx2)\
+ vec_swap_(vec_unpack_(v), idx1, idx2)
+
+
+#define vec_truncate(v, len)\
+ ((v)->length = (len) < (v)->length ? (len) : (v)->length)
+
+
+#define vec_clear(v)\
+ ((v)->length = 0)
+
+
+#define vec_first(v)\
+ (v)->data[0]
+
+
+#define vec_last(v)\
+ (v)->data[(v)->length - 1]
+
+
+#define vec_reserve(v, n)\
+ vec_reserve_(vec_unpack_(v), n)
+
+
+#define vec_compact(v)\
+ vec_compact_(vec_unpack_(v))
+
+
+#define vec_pusharr(v, arr, count)\
+ do {\
+ int i__, n__ = (count);\
+ if (vec_reserve_po2_(vec_unpack_(v), (v)->length + n__) != 0) break;\
+ for (i__ = 0; i__ < n__; i__++) {\
+ (v)->data[(v)->length++] = (arr)[i__];\
+ }\
+ } while (0)
+
+
+#define vec_extend(v, v2)\
+ vec_pusharr((v), (v2)->data, (v2)->length)
+
+
+#define vec_find(v, val, idx)\
+ do {\
+ for ((idx) = 0; (idx) < (v)->length; (idx)++) {\
+ if ((v)->data[(idx)] == (val)) break;\
+ }\
+ if ((idx) == (v)->length) (idx) = -1;\
+ } while (0)
+
+
+#define vec_remove(v, val)\
+ do {\
+ int idx__;\
+ vec_find(v, val, idx__);\
+ if (idx__ != -1) vec_splice(v, idx__, 1);\
+ } while (0)
+
+
+#define vec_reverse(v)\
+ do {\
+ int i__ = (v)->length / 2;\
+ while (i__--) {\
+ vec_swap((v), i__, (v)->length - (i__ + 1));\
+ }\
+ } while (0)
+
+
+#define vec_foreach(v, var, iter)\
+ if ( (v)->length > 0 )\
+ for ( (iter) = 0;\
+ (iter) < (v)->length && (((var) = (v)->data[(iter)]), 1);\
+ ++(iter))
+
+
+#define vec_foreach_rev(v, var, iter)\
+ if ( (v)->length > 0 )\
+ for ( (iter) = (v)->length - 1;\
+ (iter) >= 0 && (((var) = (v)->data[(iter)]), 1);\
+ --(iter))
+
+
+#define vec_foreach_ptr(v, var, iter)\
+ if ( (v)->length > 0 )\
+ for ( (iter) = 0;\
+ (iter) < (v)->length && (((var) = &(v)->data[(iter)]), 1);\
+ ++(iter))
+
+
+#define vec_foreach_ptr_rev(v, var, iter)\
+ if ( (v)->length > 0 )\
+ for ( (iter) = (v)->length - 1;\
+ (iter) >= 0 && (((var) = &(v)->data[(iter)]), 1);\
+ --(iter))
+
+
+
+int vec_expand_(char **data, int *length, int *capacity, int memsz);
+int vec_reserve_(char **data, int *length, int *capacity, int memsz, int n);
+int vec_reserve_po2_(char **data, int *length, int *capacity, int memsz,
+ int n);
+int vec_compact_(char **data, int *length, int *capacity, int memsz);
+int vec_insert_(char **data, int *length, int *capacity, int memsz,
+ int idx);
+void vec_splice_(char **data, int *length, int *capacity, int memsz,
+ int start, int count);
+void vec_swapsplice_(char **data, int *length, int *capacity, int memsz,
+ int start, int count);
+void vec_swap_(char **data, int *length, int *capacity, int memsz,
+ int idx1, int idx2);
+
+
+typedef vec_t(void*) vec_void_t;
+typedef vec_t(char*) vec_str_t;
+typedef vec_t(int) vec_int_t;
+typedef vec_t(char) vec_char_t;
+typedef vec_t(float) vec_float_t;
+typedef vec_t(double) vec_double_t;
+
+#endif
\ No newline at end of file
diff --git a/v2/internal/ffenestri/windows/EventToken.h b/v2/internal/ffenestri/windows/EventToken.h
new file mode 100644
index 000000000..885405b6b
--- /dev/null
+++ b/v2/internal/ffenestri/windows/EventToken.h
@@ -0,0 +1,68 @@
+
+
+/* this ALWAYS GENERATED file contains the definitions for the interfaces */
+
+
+ /* File created by MIDL compiler version 8.01.0622 */
+/* @@MIDL_FILE_HEADING( ) */
+
+
+
+/* verify that the version is high enough to compile this file*/
+#ifndef __REQUIRED_RPCNDR_H_VERSION__
+#define __REQUIRED_RPCNDR_H_VERSION__ 500
+#endif
+
+/* verify that the version is high enough to compile this file*/
+#ifndef __REQUIRED_RPCSAL_H_VERSION__
+#define __REQUIRED_RPCSAL_H_VERSION__ 100
+#endif
+
+#include "rpc.h"
+#include "rpcndr.h"
+
+#ifndef __RPCNDR_H_VERSION__
+#error this stub requires an updated version of
+#endif /* __RPCNDR_H_VERSION__ */
+
+
+#ifndef __eventtoken_h__
+#define __eventtoken_h__
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+#pragma once
+#endif
+
+/* Forward Declarations */
+
+#ifdef __cplusplus
+extern "C"{
+#endif
+
+
+/* interface __MIDL_itf_eventtoken_0000_0000 */
+/* [local] */
+
+// Microsoft Windows
+// Copyright (c) Microsoft Corporation. All rights reserved.
+#pragma once
+typedef struct EventRegistrationToken
+ {
+ __int64 value;
+ } EventRegistrationToken;
+
+
+
+extern RPC_IF_HANDLE __MIDL_itf_eventtoken_0000_0000_v0_0_c_ifspec;
+extern RPC_IF_HANDLE __MIDL_itf_eventtoken_0000_0000_v0_0_s_ifspec;
+
+/* Additional Prototypes for ALL interfaces */
+
+/* end of Additional Prototypes */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/v2/internal/ffenestri/windows/WebView2.h b/v2/internal/ffenestri/windows/WebView2.h
new file mode 100644
index 000000000..44cd67035
--- /dev/null
+++ b/v2/internal/ffenestri/windows/WebView2.h
@@ -0,0 +1,12693 @@
+
+
+/* this ALWAYS GENERATED file contains the definitions for the interfaces */
+
+
+ /* File created by MIDL compiler version 8.xx.xxxx */
+/* at a redacted point in time
+ */
+/* Compiler settings for ../../edge_embedded_browser/client/win/current/webview2.idl:
+ Oicf, W1, Zp8, env=Win64 (32b run), target_arch=AMD64 8.xx.xxxx
+ protocol : dce , ms_ext, c_ext, robust
+ error checks: allocation ref bounds_check enum stub_data
+ VC __declspec() decoration level:
+ __declspec(uuid()), __declspec(selectany), __declspec(novtable)
+ DECLSPEC_UUID(), MIDL_INTERFACE()
+*/
+/* @@MIDL_FILE_HEADING( ) */
+
+#pragma warning( disable: 4049 ) /* more than 64k source lines */
+
+
+/* verify that the version is high enough to compile this file*/
+#ifndef __REQUIRED_RPCNDR_H_VERSION__
+#define __REQUIRED_RPCNDR_H_VERSION__ 475
+#endif
+
+#include "rpc.h"
+#include "rpcndr.h"
+
+#ifndef __RPCNDR_H_VERSION__
+#error this stub requires an updated version of
+#endif /* __RPCNDR_H_VERSION__ */
+
+
+#ifndef __webview2_h__
+#define __webview2_h__
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+#pragma once
+#endif
+
+/* Forward Declarations */
+
+#ifndef __ICoreWebView2AcceleratorKeyPressedEventArgs_FWD_DEFINED__
+#define __ICoreWebView2AcceleratorKeyPressedEventArgs_FWD_DEFINED__
+typedef interface ICoreWebView2AcceleratorKeyPressedEventArgs ICoreWebView2AcceleratorKeyPressedEventArgs;
+
+#endif /* __ICoreWebView2AcceleratorKeyPressedEventArgs_FWD_DEFINED__ */
+
+
+#ifndef __ICoreWebView2AcceleratorKeyPressedEventHandler_FWD_DEFINED__
+#define __ICoreWebView2AcceleratorKeyPressedEventHandler_FWD_DEFINED__
+typedef interface ICoreWebView2AcceleratorKeyPressedEventHandler ICoreWebView2AcceleratorKeyPressedEventHandler;
+
+#endif /* __ICoreWebView2AcceleratorKeyPressedEventHandler_FWD_DEFINED__ */
+
+
+#ifndef __ICoreWebView2AddScriptToExecuteOnDocumentCreatedCompletedHandler_FWD_DEFINED__
+#define __ICoreWebView2AddScriptToExecuteOnDocumentCreatedCompletedHandler_FWD_DEFINED__
+typedef interface ICoreWebView2AddScriptToExecuteOnDocumentCreatedCompletedHandler ICoreWebView2AddScriptToExecuteOnDocumentCreatedCompletedHandler;
+
+#endif /* __ICoreWebView2AddScriptToExecuteOnDocumentCreatedCompletedHandler_FWD_DEFINED__ */
+
+
+#ifndef __ICoreWebView2CallDevToolsProtocolMethodCompletedHandler_FWD_DEFINED__
+#define __ICoreWebView2CallDevToolsProtocolMethodCompletedHandler_FWD_DEFINED__
+typedef interface ICoreWebView2CallDevToolsProtocolMethodCompletedHandler ICoreWebView2CallDevToolsProtocolMethodCompletedHandler;
+
+#endif /* __ICoreWebView2CallDevToolsProtocolMethodCompletedHandler_FWD_DEFINED__ */
+
+
+#ifndef __ICoreWebView2CapturePreviewCompletedHandler_FWD_DEFINED__
+#define __ICoreWebView2CapturePreviewCompletedHandler_FWD_DEFINED__
+typedef interface ICoreWebView2CapturePreviewCompletedHandler ICoreWebView2CapturePreviewCompletedHandler;
+
+#endif /* __ICoreWebView2CapturePreviewCompletedHandler_FWD_DEFINED__ */
+
+
+#ifndef __ICoreWebView2_FWD_DEFINED__
+#define __ICoreWebView2_FWD_DEFINED__
+typedef interface ICoreWebView2 ICoreWebView2;
+
+#endif /* __ICoreWebView2_FWD_DEFINED__ */
+
+
+#ifndef __ICoreWebView2_2_FWD_DEFINED__
+#define __ICoreWebView2_2_FWD_DEFINED__
+typedef interface ICoreWebView2_2 ICoreWebView2_2;
+
+#endif /* __ICoreWebView2_2_FWD_DEFINED__ */
+
+
+#ifndef __ICoreWebView2_3_FWD_DEFINED__
+#define __ICoreWebView2_3_FWD_DEFINED__
+typedef interface ICoreWebView2_3 ICoreWebView2_3;
+
+#endif /* __ICoreWebView2_3_FWD_DEFINED__ */
+
+
+#ifndef __ICoreWebView2CompositionController_FWD_DEFINED__
+#define __ICoreWebView2CompositionController_FWD_DEFINED__
+typedef interface ICoreWebView2CompositionController ICoreWebView2CompositionController;
+
+#endif /* __ICoreWebView2CompositionController_FWD_DEFINED__ */
+
+
+#ifndef __ICoreWebView2CompositionController2_FWD_DEFINED__
+#define __ICoreWebView2CompositionController2_FWD_DEFINED__
+typedef interface ICoreWebView2CompositionController2 ICoreWebView2CompositionController2;
+
+#endif /* __ICoreWebView2CompositionController2_FWD_DEFINED__ */
+
+
+#ifndef __ICoreWebView2Controller_FWD_DEFINED__
+#define __ICoreWebView2Controller_FWD_DEFINED__
+typedef interface ICoreWebView2Controller ICoreWebView2Controller;
+
+#endif /* __ICoreWebView2Controller_FWD_DEFINED__ */
+
+
+#ifndef __ICoreWebView2Controller2_FWD_DEFINED__
+#define __ICoreWebView2Controller2_FWD_DEFINED__
+typedef interface ICoreWebView2Controller2 ICoreWebView2Controller2;
+
+#endif /* __ICoreWebView2Controller2_FWD_DEFINED__ */
+
+
+#ifndef __ICoreWebView2Controller3_FWD_DEFINED__
+#define __ICoreWebView2Controller3_FWD_DEFINED__
+typedef interface ICoreWebView2Controller3 ICoreWebView2Controller3;
+
+#endif /* __ICoreWebView2Controller3_FWD_DEFINED__ */
+
+
+#ifndef __ICoreWebView2ContentLoadingEventArgs_FWD_DEFINED__
+#define __ICoreWebView2ContentLoadingEventArgs_FWD_DEFINED__
+typedef interface ICoreWebView2ContentLoadingEventArgs ICoreWebView2ContentLoadingEventArgs;
+
+#endif /* __ICoreWebView2ContentLoadingEventArgs_FWD_DEFINED__ */
+
+
+#ifndef __ICoreWebView2ContentLoadingEventHandler_FWD_DEFINED__
+#define __ICoreWebView2ContentLoadingEventHandler_FWD_DEFINED__
+typedef interface ICoreWebView2ContentLoadingEventHandler ICoreWebView2ContentLoadingEventHandler;
+
+#endif /* __ICoreWebView2ContentLoadingEventHandler_FWD_DEFINED__ */
+
+
+#ifndef __ICoreWebView2Cookie_FWD_DEFINED__
+#define __ICoreWebView2Cookie_FWD_DEFINED__
+typedef interface ICoreWebView2Cookie ICoreWebView2Cookie;
+
+#endif /* __ICoreWebView2Cookie_FWD_DEFINED__ */
+
+
+#ifndef __ICoreWebView2CookieList_FWD_DEFINED__
+#define __ICoreWebView2CookieList_FWD_DEFINED__
+typedef interface ICoreWebView2CookieList ICoreWebView2CookieList;
+
+#endif /* __ICoreWebView2CookieList_FWD_DEFINED__ */
+
+
+#ifndef __ICoreWebView2CookieManager_FWD_DEFINED__
+#define __ICoreWebView2CookieManager_FWD_DEFINED__
+typedef interface ICoreWebView2CookieManager ICoreWebView2CookieManager;
+
+#endif /* __ICoreWebView2CookieManager_FWD_DEFINED__ */
+
+
+#ifndef __ICoreWebView2CreateCoreWebView2CompositionControllerCompletedHandler_FWD_DEFINED__
+#define __ICoreWebView2CreateCoreWebView2CompositionControllerCompletedHandler_FWD_DEFINED__
+typedef interface ICoreWebView2CreateCoreWebView2CompositionControllerCompletedHandler ICoreWebView2CreateCoreWebView2CompositionControllerCompletedHandler;
+
+#endif /* __ICoreWebView2CreateCoreWebView2CompositionControllerCompletedHandler_FWD_DEFINED__ */
+
+
+#ifndef __ICoreWebView2CreateCoreWebView2ControllerCompletedHandler_FWD_DEFINED__
+#define __ICoreWebView2CreateCoreWebView2ControllerCompletedHandler_FWD_DEFINED__
+typedef interface ICoreWebView2CreateCoreWebView2ControllerCompletedHandler ICoreWebView2CreateCoreWebView2ControllerCompletedHandler;
+
+#endif /* __ICoreWebView2CreateCoreWebView2ControllerCompletedHandler_FWD_DEFINED__ */
+
+
+#ifndef __ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler_FWD_DEFINED__
+#define __ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler_FWD_DEFINED__
+typedef interface ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler;
+
+#endif /* __ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler_FWD_DEFINED__ */
+
+
+#ifndef __ICoreWebView2ContainsFullScreenElementChangedEventHandler_FWD_DEFINED__
+#define __ICoreWebView2ContainsFullScreenElementChangedEventHandler_FWD_DEFINED__
+typedef interface ICoreWebView2ContainsFullScreenElementChangedEventHandler ICoreWebView2ContainsFullScreenElementChangedEventHandler;
+
+#endif /* __ICoreWebView2ContainsFullScreenElementChangedEventHandler_FWD_DEFINED__ */
+
+
+#ifndef __ICoreWebView2CursorChangedEventHandler_FWD_DEFINED__
+#define __ICoreWebView2CursorChangedEventHandler_FWD_DEFINED__
+typedef interface ICoreWebView2CursorChangedEventHandler ICoreWebView2CursorChangedEventHandler;
+
+#endif /* __ICoreWebView2CursorChangedEventHandler_FWD_DEFINED__ */
+
+
+#ifndef __ICoreWebView2DocumentTitleChangedEventHandler_FWD_DEFINED__
+#define __ICoreWebView2DocumentTitleChangedEventHandler_FWD_DEFINED__
+typedef interface ICoreWebView2DocumentTitleChangedEventHandler ICoreWebView2DocumentTitleChangedEventHandler;
+
+#endif /* __ICoreWebView2DocumentTitleChangedEventHandler_FWD_DEFINED__ */
+
+
+#ifndef __ICoreWebView2DOMContentLoadedEventArgs_FWD_DEFINED__
+#define __ICoreWebView2DOMContentLoadedEventArgs_FWD_DEFINED__
+typedef interface ICoreWebView2DOMContentLoadedEventArgs ICoreWebView2DOMContentLoadedEventArgs;
+
+#endif /* __ICoreWebView2DOMContentLoadedEventArgs_FWD_DEFINED__ */
+
+
+#ifndef __ICoreWebView2DOMContentLoadedEventHandler_FWD_DEFINED__
+#define __ICoreWebView2DOMContentLoadedEventHandler_FWD_DEFINED__
+typedef interface ICoreWebView2DOMContentLoadedEventHandler ICoreWebView2DOMContentLoadedEventHandler;
+
+#endif /* __ICoreWebView2DOMContentLoadedEventHandler_FWD_DEFINED__ */
+
+
+#ifndef __ICoreWebView2Deferral_FWD_DEFINED__
+#define __ICoreWebView2Deferral_FWD_DEFINED__
+typedef interface ICoreWebView2Deferral ICoreWebView2Deferral;
+
+#endif /* __ICoreWebView2Deferral_FWD_DEFINED__ */
+
+
+#ifndef __ICoreWebView2DevToolsProtocolEventReceivedEventArgs_FWD_DEFINED__
+#define __ICoreWebView2DevToolsProtocolEventReceivedEventArgs_FWD_DEFINED__
+typedef interface ICoreWebView2DevToolsProtocolEventReceivedEventArgs ICoreWebView2DevToolsProtocolEventReceivedEventArgs;
+
+#endif /* __ICoreWebView2DevToolsProtocolEventReceivedEventArgs_FWD_DEFINED__ */
+
+
+#ifndef __ICoreWebView2DevToolsProtocolEventReceivedEventHandler_FWD_DEFINED__
+#define __ICoreWebView2DevToolsProtocolEventReceivedEventHandler_FWD_DEFINED__
+typedef interface ICoreWebView2DevToolsProtocolEventReceivedEventHandler ICoreWebView2DevToolsProtocolEventReceivedEventHandler;
+
+#endif /* __ICoreWebView2DevToolsProtocolEventReceivedEventHandler_FWD_DEFINED__ */
+
+
+#ifndef __ICoreWebView2DevToolsProtocolEventReceiver_FWD_DEFINED__
+#define __ICoreWebView2DevToolsProtocolEventReceiver_FWD_DEFINED__
+typedef interface ICoreWebView2DevToolsProtocolEventReceiver ICoreWebView2DevToolsProtocolEventReceiver;
+
+#endif /* __ICoreWebView2DevToolsProtocolEventReceiver_FWD_DEFINED__ */
+
+
+#ifndef __ICoreWebView2Environment_FWD_DEFINED__
+#define __ICoreWebView2Environment_FWD_DEFINED__
+typedef interface ICoreWebView2Environment ICoreWebView2Environment;
+
+#endif /* __ICoreWebView2Environment_FWD_DEFINED__ */
+
+
+#ifndef __ICoreWebView2Environment2_FWD_DEFINED__
+#define __ICoreWebView2Environment2_FWD_DEFINED__
+typedef interface ICoreWebView2Environment2 ICoreWebView2Environment2;
+
+#endif /* __ICoreWebView2Environment2_FWD_DEFINED__ */
+
+
+#ifndef __ICoreWebView2Environment3_FWD_DEFINED__
+#define __ICoreWebView2Environment3_FWD_DEFINED__
+typedef interface ICoreWebView2Environment3 ICoreWebView2Environment3;
+
+#endif /* __ICoreWebView2Environment3_FWD_DEFINED__ */
+
+
+#ifndef __ICoreWebView2Environment4_FWD_DEFINED__
+#define __ICoreWebView2Environment4_FWD_DEFINED__
+typedef interface ICoreWebView2Environment4 ICoreWebView2Environment4;
+
+#endif /* __ICoreWebView2Environment4_FWD_DEFINED__ */
+
+
+#ifndef __ICoreWebView2EnvironmentOptions_FWD_DEFINED__
+#define __ICoreWebView2EnvironmentOptions_FWD_DEFINED__
+typedef interface ICoreWebView2EnvironmentOptions ICoreWebView2EnvironmentOptions;
+
+#endif /* __ICoreWebView2EnvironmentOptions_FWD_DEFINED__ */
+
+
+#ifndef __ICoreWebView2ExecuteScriptCompletedHandler_FWD_DEFINED__
+#define __ICoreWebView2ExecuteScriptCompletedHandler_FWD_DEFINED__
+typedef interface ICoreWebView2ExecuteScriptCompletedHandler ICoreWebView2ExecuteScriptCompletedHandler;
+
+#endif /* __ICoreWebView2ExecuteScriptCompletedHandler_FWD_DEFINED__ */
+
+
+#ifndef __ICoreWebView2FrameInfo_FWD_DEFINED__
+#define __ICoreWebView2FrameInfo_FWD_DEFINED__
+typedef interface ICoreWebView2FrameInfo ICoreWebView2FrameInfo;
+
+#endif /* __ICoreWebView2FrameInfo_FWD_DEFINED__ */
+
+
+#ifndef __ICoreWebView2FrameInfoCollection_FWD_DEFINED__
+#define __ICoreWebView2FrameInfoCollection_FWD_DEFINED__
+typedef interface ICoreWebView2FrameInfoCollection ICoreWebView2FrameInfoCollection;
+
+#endif /* __ICoreWebView2FrameInfoCollection_FWD_DEFINED__ */
+
+
+#ifndef __ICoreWebView2FrameInfoCollectionIterator_FWD_DEFINED__
+#define __ICoreWebView2FrameInfoCollectionIterator_FWD_DEFINED__
+typedef interface ICoreWebView2FrameInfoCollectionIterator ICoreWebView2FrameInfoCollectionIterator;
+
+#endif /* __ICoreWebView2FrameInfoCollectionIterator_FWD_DEFINED__ */
+
+
+#ifndef __ICoreWebView2FocusChangedEventHandler_FWD_DEFINED__
+#define __ICoreWebView2FocusChangedEventHandler_FWD_DEFINED__
+typedef interface ICoreWebView2FocusChangedEventHandler ICoreWebView2FocusChangedEventHandler;
+
+#endif /* __ICoreWebView2FocusChangedEventHandler_FWD_DEFINED__ */
+
+
+#ifndef __ICoreWebView2GetCookiesCompletedHandler_FWD_DEFINED__
+#define __ICoreWebView2GetCookiesCompletedHandler_FWD_DEFINED__
+typedef interface ICoreWebView2GetCookiesCompletedHandler ICoreWebView2GetCookiesCompletedHandler;
+
+#endif /* __ICoreWebView2GetCookiesCompletedHandler_FWD_DEFINED__ */
+
+
+#ifndef __ICoreWebView2HistoryChangedEventHandler_FWD_DEFINED__
+#define __ICoreWebView2HistoryChangedEventHandler_FWD_DEFINED__
+typedef interface ICoreWebView2HistoryChangedEventHandler ICoreWebView2HistoryChangedEventHandler;
+
+#endif /* __ICoreWebView2HistoryChangedEventHandler_FWD_DEFINED__ */
+
+
+#ifndef __ICoreWebView2HttpHeadersCollectionIterator_FWD_DEFINED__
+#define __ICoreWebView2HttpHeadersCollectionIterator_FWD_DEFINED__
+typedef interface ICoreWebView2HttpHeadersCollectionIterator ICoreWebView2HttpHeadersCollectionIterator;
+
+#endif /* __ICoreWebView2HttpHeadersCollectionIterator_FWD_DEFINED__ */
+
+
+#ifndef __ICoreWebView2HttpRequestHeaders_FWD_DEFINED__
+#define __ICoreWebView2HttpRequestHeaders_FWD_DEFINED__
+typedef interface ICoreWebView2HttpRequestHeaders ICoreWebView2HttpRequestHeaders;
+
+#endif /* __ICoreWebView2HttpRequestHeaders_FWD_DEFINED__ */
+
+
+#ifndef __ICoreWebView2HttpResponseHeaders_FWD_DEFINED__
+#define __ICoreWebView2HttpResponseHeaders_FWD_DEFINED__
+typedef interface ICoreWebView2HttpResponseHeaders ICoreWebView2HttpResponseHeaders;
+
+#endif /* __ICoreWebView2HttpResponseHeaders_FWD_DEFINED__ */
+
+
+#ifndef __ICoreWebView2Interop_FWD_DEFINED__
+#define __ICoreWebView2Interop_FWD_DEFINED__
+typedef interface ICoreWebView2Interop ICoreWebView2Interop;
+
+#endif /* __ICoreWebView2Interop_FWD_DEFINED__ */
+
+
+#ifndef __ICoreWebView2MoveFocusRequestedEventArgs_FWD_DEFINED__
+#define __ICoreWebView2MoveFocusRequestedEventArgs_FWD_DEFINED__
+typedef interface ICoreWebView2MoveFocusRequestedEventArgs ICoreWebView2MoveFocusRequestedEventArgs;
+
+#endif /* __ICoreWebView2MoveFocusRequestedEventArgs_FWD_DEFINED__ */
+
+
+#ifndef __ICoreWebView2MoveFocusRequestedEventHandler_FWD_DEFINED__
+#define __ICoreWebView2MoveFocusRequestedEventHandler_FWD_DEFINED__
+typedef interface ICoreWebView2MoveFocusRequestedEventHandler ICoreWebView2MoveFocusRequestedEventHandler;
+
+#endif /* __ICoreWebView2MoveFocusRequestedEventHandler_FWD_DEFINED__ */
+
+
+#ifndef __ICoreWebView2NavigationCompletedEventArgs_FWD_DEFINED__
+#define __ICoreWebView2NavigationCompletedEventArgs_FWD_DEFINED__
+typedef interface ICoreWebView2NavigationCompletedEventArgs ICoreWebView2NavigationCompletedEventArgs;
+
+#endif /* __ICoreWebView2NavigationCompletedEventArgs_FWD_DEFINED__ */
+
+
+#ifndef __ICoreWebView2NavigationCompletedEventHandler_FWD_DEFINED__
+#define __ICoreWebView2NavigationCompletedEventHandler_FWD_DEFINED__
+typedef interface ICoreWebView2NavigationCompletedEventHandler ICoreWebView2NavigationCompletedEventHandler;
+
+#endif /* __ICoreWebView2NavigationCompletedEventHandler_FWD_DEFINED__ */
+
+
+#ifndef __ICoreWebView2NavigationStartingEventArgs_FWD_DEFINED__
+#define __ICoreWebView2NavigationStartingEventArgs_FWD_DEFINED__
+typedef interface ICoreWebView2NavigationStartingEventArgs ICoreWebView2NavigationStartingEventArgs;
+
+#endif /* __ICoreWebView2NavigationStartingEventArgs_FWD_DEFINED__ */
+
+
+#ifndef __ICoreWebView2NavigationStartingEventHandler_FWD_DEFINED__
+#define __ICoreWebView2NavigationStartingEventHandler_FWD_DEFINED__
+typedef interface ICoreWebView2NavigationStartingEventHandler ICoreWebView2NavigationStartingEventHandler;
+
+#endif /* __ICoreWebView2NavigationStartingEventHandler_FWD_DEFINED__ */
+
+
+#ifndef __ICoreWebView2NewBrowserVersionAvailableEventHandler_FWD_DEFINED__
+#define __ICoreWebView2NewBrowserVersionAvailableEventHandler_FWD_DEFINED__
+typedef interface ICoreWebView2NewBrowserVersionAvailableEventHandler ICoreWebView2NewBrowserVersionAvailableEventHandler;
+
+#endif /* __ICoreWebView2NewBrowserVersionAvailableEventHandler_FWD_DEFINED__ */
+
+
+#ifndef __ICoreWebView2NewWindowRequestedEventArgs_FWD_DEFINED__
+#define __ICoreWebView2NewWindowRequestedEventArgs_FWD_DEFINED__
+typedef interface ICoreWebView2NewWindowRequestedEventArgs ICoreWebView2NewWindowRequestedEventArgs;
+
+#endif /* __ICoreWebView2NewWindowRequestedEventArgs_FWD_DEFINED__ */
+
+
+#ifndef __ICoreWebView2NewWindowRequestedEventHandler_FWD_DEFINED__
+#define __ICoreWebView2NewWindowRequestedEventHandler_FWD_DEFINED__
+typedef interface ICoreWebView2NewWindowRequestedEventHandler ICoreWebView2NewWindowRequestedEventHandler;
+
+#endif /* __ICoreWebView2NewWindowRequestedEventHandler_FWD_DEFINED__ */
+
+
+#ifndef __ICoreWebView2PermissionRequestedEventArgs_FWD_DEFINED__
+#define __ICoreWebView2PermissionRequestedEventArgs_FWD_DEFINED__
+typedef interface ICoreWebView2PermissionRequestedEventArgs ICoreWebView2PermissionRequestedEventArgs;
+
+#endif /* __ICoreWebView2PermissionRequestedEventArgs_FWD_DEFINED__ */
+
+
+#ifndef __ICoreWebView2PermissionRequestedEventHandler_FWD_DEFINED__
+#define __ICoreWebView2PermissionRequestedEventHandler_FWD_DEFINED__
+typedef interface ICoreWebView2PermissionRequestedEventHandler ICoreWebView2PermissionRequestedEventHandler;
+
+#endif /* __ICoreWebView2PermissionRequestedEventHandler_FWD_DEFINED__ */
+
+
+#ifndef __ICoreWebView2PointerInfo_FWD_DEFINED__
+#define __ICoreWebView2PointerInfo_FWD_DEFINED__
+typedef interface ICoreWebView2PointerInfo ICoreWebView2PointerInfo;
+
+#endif /* __ICoreWebView2PointerInfo_FWD_DEFINED__ */
+
+
+#ifndef __ICoreWebView2ProcessFailedEventArgs_FWD_DEFINED__
+#define __ICoreWebView2ProcessFailedEventArgs_FWD_DEFINED__
+typedef interface ICoreWebView2ProcessFailedEventArgs ICoreWebView2ProcessFailedEventArgs;
+
+#endif /* __ICoreWebView2ProcessFailedEventArgs_FWD_DEFINED__ */
+
+
+#ifndef __ICoreWebView2ProcessFailedEventArgs2_FWD_DEFINED__
+#define __ICoreWebView2ProcessFailedEventArgs2_FWD_DEFINED__
+typedef interface ICoreWebView2ProcessFailedEventArgs2 ICoreWebView2ProcessFailedEventArgs2;
+
+#endif /* __ICoreWebView2ProcessFailedEventArgs2_FWD_DEFINED__ */
+
+
+#ifndef __ICoreWebView2ProcessFailedEventHandler_FWD_DEFINED__
+#define __ICoreWebView2ProcessFailedEventHandler_FWD_DEFINED__
+typedef interface ICoreWebView2ProcessFailedEventHandler ICoreWebView2ProcessFailedEventHandler;
+
+#endif /* __ICoreWebView2ProcessFailedEventHandler_FWD_DEFINED__ */
+
+
+#ifndef __ICoreWebView2RasterizationScaleChangedEventHandler_FWD_DEFINED__
+#define __ICoreWebView2RasterizationScaleChangedEventHandler_FWD_DEFINED__
+typedef interface ICoreWebView2RasterizationScaleChangedEventHandler ICoreWebView2RasterizationScaleChangedEventHandler;
+
+#endif /* __ICoreWebView2RasterizationScaleChangedEventHandler_FWD_DEFINED__ */
+
+
+#ifndef __ICoreWebView2ScriptDialogOpeningEventArgs_FWD_DEFINED__
+#define __ICoreWebView2ScriptDialogOpeningEventArgs_FWD_DEFINED__
+typedef interface ICoreWebView2ScriptDialogOpeningEventArgs ICoreWebView2ScriptDialogOpeningEventArgs;
+
+#endif /* __ICoreWebView2ScriptDialogOpeningEventArgs_FWD_DEFINED__ */
+
+
+#ifndef __ICoreWebView2ScriptDialogOpeningEventHandler_FWD_DEFINED__
+#define __ICoreWebView2ScriptDialogOpeningEventHandler_FWD_DEFINED__
+typedef interface ICoreWebView2ScriptDialogOpeningEventHandler ICoreWebView2ScriptDialogOpeningEventHandler;
+
+#endif /* __ICoreWebView2ScriptDialogOpeningEventHandler_FWD_DEFINED__ */
+
+
+#ifndef __ICoreWebView2Settings_FWD_DEFINED__
+#define __ICoreWebView2Settings_FWD_DEFINED__
+typedef interface ICoreWebView2Settings ICoreWebView2Settings;
+
+#endif /* __ICoreWebView2Settings_FWD_DEFINED__ */
+
+
+#ifndef __ICoreWebView2Settings2_FWD_DEFINED__
+#define __ICoreWebView2Settings2_FWD_DEFINED__
+typedef interface ICoreWebView2Settings2 ICoreWebView2Settings2;
+
+#endif /* __ICoreWebView2Settings2_FWD_DEFINED__ */
+
+
+#ifndef __ICoreWebView2Settings3_FWD_DEFINED__
+#define __ICoreWebView2Settings3_FWD_DEFINED__
+typedef interface ICoreWebView2Settings3 ICoreWebView2Settings3;
+
+#endif /* __ICoreWebView2Settings3_FWD_DEFINED__ */
+
+
+#ifndef __ICoreWebView2SourceChangedEventArgs_FWD_DEFINED__
+#define __ICoreWebView2SourceChangedEventArgs_FWD_DEFINED__
+typedef interface ICoreWebView2SourceChangedEventArgs ICoreWebView2SourceChangedEventArgs;
+
+#endif /* __ICoreWebView2SourceChangedEventArgs_FWD_DEFINED__ */
+
+
+#ifndef __ICoreWebView2SourceChangedEventHandler_FWD_DEFINED__
+#define __ICoreWebView2SourceChangedEventHandler_FWD_DEFINED__
+typedef interface ICoreWebView2SourceChangedEventHandler ICoreWebView2SourceChangedEventHandler;
+
+#endif /* __ICoreWebView2SourceChangedEventHandler_FWD_DEFINED__ */
+
+
+#ifndef __ICoreWebView2TrySuspendCompletedHandler_FWD_DEFINED__
+#define __ICoreWebView2TrySuspendCompletedHandler_FWD_DEFINED__
+typedef interface ICoreWebView2TrySuspendCompletedHandler ICoreWebView2TrySuspendCompletedHandler;
+
+#endif /* __ICoreWebView2TrySuspendCompletedHandler_FWD_DEFINED__ */
+
+
+#ifndef __ICoreWebView2WebMessageReceivedEventArgs_FWD_DEFINED__
+#define __ICoreWebView2WebMessageReceivedEventArgs_FWD_DEFINED__
+typedef interface ICoreWebView2WebMessageReceivedEventArgs ICoreWebView2WebMessageReceivedEventArgs;
+
+#endif /* __ICoreWebView2WebMessageReceivedEventArgs_FWD_DEFINED__ */
+
+
+#ifndef __ICoreWebView2WebMessageReceivedEventHandler_FWD_DEFINED__
+#define __ICoreWebView2WebMessageReceivedEventHandler_FWD_DEFINED__
+typedef interface ICoreWebView2WebMessageReceivedEventHandler ICoreWebView2WebMessageReceivedEventHandler;
+
+#endif /* __ICoreWebView2WebMessageReceivedEventHandler_FWD_DEFINED__ */
+
+
+#ifndef __ICoreWebView2WebResourceRequest_FWD_DEFINED__
+#define __ICoreWebView2WebResourceRequest_FWD_DEFINED__
+typedef interface ICoreWebView2WebResourceRequest ICoreWebView2WebResourceRequest;
+
+#endif /* __ICoreWebView2WebResourceRequest_FWD_DEFINED__ */
+
+
+#ifndef __ICoreWebView2WebResourceRequestedEventArgs_FWD_DEFINED__
+#define __ICoreWebView2WebResourceRequestedEventArgs_FWD_DEFINED__
+typedef interface ICoreWebView2WebResourceRequestedEventArgs ICoreWebView2WebResourceRequestedEventArgs;
+
+#endif /* __ICoreWebView2WebResourceRequestedEventArgs_FWD_DEFINED__ */
+
+
+#ifndef __ICoreWebView2WebResourceRequestedEventHandler_FWD_DEFINED__
+#define __ICoreWebView2WebResourceRequestedEventHandler_FWD_DEFINED__
+typedef interface ICoreWebView2WebResourceRequestedEventHandler ICoreWebView2WebResourceRequestedEventHandler;
+
+#endif /* __ICoreWebView2WebResourceRequestedEventHandler_FWD_DEFINED__ */
+
+
+#ifndef __ICoreWebView2WebResourceResponse_FWD_DEFINED__
+#define __ICoreWebView2WebResourceResponse_FWD_DEFINED__
+typedef interface ICoreWebView2WebResourceResponse ICoreWebView2WebResourceResponse;
+
+#endif /* __ICoreWebView2WebResourceResponse_FWD_DEFINED__ */
+
+
+#ifndef __ICoreWebView2WebResourceResponseReceivedEventHandler_FWD_DEFINED__
+#define __ICoreWebView2WebResourceResponseReceivedEventHandler_FWD_DEFINED__
+typedef interface ICoreWebView2WebResourceResponseReceivedEventHandler ICoreWebView2WebResourceResponseReceivedEventHandler;
+
+#endif /* __ICoreWebView2WebResourceResponseReceivedEventHandler_FWD_DEFINED__ */
+
+
+#ifndef __ICoreWebView2WebResourceResponseReceivedEventArgs_FWD_DEFINED__
+#define __ICoreWebView2WebResourceResponseReceivedEventArgs_FWD_DEFINED__
+typedef interface ICoreWebView2WebResourceResponseReceivedEventArgs ICoreWebView2WebResourceResponseReceivedEventArgs;
+
+#endif /* __ICoreWebView2WebResourceResponseReceivedEventArgs_FWD_DEFINED__ */
+
+
+#ifndef __ICoreWebView2WebResourceResponseView_FWD_DEFINED__
+#define __ICoreWebView2WebResourceResponseView_FWD_DEFINED__
+typedef interface ICoreWebView2WebResourceResponseView ICoreWebView2WebResourceResponseView;
+
+#endif /* __ICoreWebView2WebResourceResponseView_FWD_DEFINED__ */
+
+
+#ifndef __ICoreWebView2WebResourceResponseViewGetContentCompletedHandler_FWD_DEFINED__
+#define __ICoreWebView2WebResourceResponseViewGetContentCompletedHandler_FWD_DEFINED__
+typedef interface ICoreWebView2WebResourceResponseViewGetContentCompletedHandler ICoreWebView2WebResourceResponseViewGetContentCompletedHandler;
+
+#endif /* __ICoreWebView2WebResourceResponseViewGetContentCompletedHandler_FWD_DEFINED__ */
+
+
+#ifndef __ICoreWebView2WindowCloseRequestedEventHandler_FWD_DEFINED__
+#define __ICoreWebView2WindowCloseRequestedEventHandler_FWD_DEFINED__
+typedef interface ICoreWebView2WindowCloseRequestedEventHandler ICoreWebView2WindowCloseRequestedEventHandler;
+
+#endif /* __ICoreWebView2WindowCloseRequestedEventHandler_FWD_DEFINED__ */
+
+
+#ifndef __ICoreWebView2WindowFeatures_FWD_DEFINED__
+#define __ICoreWebView2WindowFeatures_FWD_DEFINED__
+typedef interface ICoreWebView2WindowFeatures ICoreWebView2WindowFeatures;
+
+#endif /* __ICoreWebView2WindowFeatures_FWD_DEFINED__ */
+
+
+#ifndef __ICoreWebView2ZoomFactorChangedEventHandler_FWD_DEFINED__
+#define __ICoreWebView2ZoomFactorChangedEventHandler_FWD_DEFINED__
+typedef interface ICoreWebView2ZoomFactorChangedEventHandler ICoreWebView2ZoomFactorChangedEventHandler;
+
+#endif /* __ICoreWebView2ZoomFactorChangedEventHandler_FWD_DEFINED__ */
+
+
+#ifndef __ICoreWebView2CompositionControllerInterop_FWD_DEFINED__
+#define __ICoreWebView2CompositionControllerInterop_FWD_DEFINED__
+typedef interface ICoreWebView2CompositionControllerInterop ICoreWebView2CompositionControllerInterop;
+
+#endif /* __ICoreWebView2CompositionControllerInterop_FWD_DEFINED__ */
+
+
+#ifndef __ICoreWebView2EnvironmentInterop_FWD_DEFINED__
+#define __ICoreWebView2EnvironmentInterop_FWD_DEFINED__
+typedef interface ICoreWebView2EnvironmentInterop ICoreWebView2EnvironmentInterop;
+
+#endif /* __ICoreWebView2EnvironmentInterop_FWD_DEFINED__ */
+
+
+/* header files for imported files */
+#include "objidl.h"
+#include "oaidl.h"
+#include "EventToken.h"
+
+#ifdef __cplusplus
+extern "C"{
+#endif
+
+
+
+#ifndef __WebView2_LIBRARY_DEFINED__
+#define __WebView2_LIBRARY_DEFINED__
+
+/* library WebView2 */
+/* [version][uuid] */
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+typedef /* [v1_enum] */
+enum COREWEBVIEW2_CAPTURE_PREVIEW_IMAGE_FORMAT
+ {
+ COREWEBVIEW2_CAPTURE_PREVIEW_IMAGE_FORMAT_PNG = 0,
+ COREWEBVIEW2_CAPTURE_PREVIEW_IMAGE_FORMAT_JPEG = ( COREWEBVIEW2_CAPTURE_PREVIEW_IMAGE_FORMAT_PNG + 1 )
+ } COREWEBVIEW2_CAPTURE_PREVIEW_IMAGE_FORMAT;
+
+typedef /* [v1_enum] */
+enum COREWEBVIEW2_COOKIE_SAME_SITE_KIND
+ {
+ COREWEBVIEW2_COOKIE_SAME_SITE_KIND_NONE = 0,
+ COREWEBVIEW2_COOKIE_SAME_SITE_KIND_LAX = ( COREWEBVIEW2_COOKIE_SAME_SITE_KIND_NONE + 1 ) ,
+ COREWEBVIEW2_COOKIE_SAME_SITE_KIND_STRICT = ( COREWEBVIEW2_COOKIE_SAME_SITE_KIND_LAX + 1 )
+ } COREWEBVIEW2_COOKIE_SAME_SITE_KIND;
+
+typedef /* [v1_enum] */
+enum COREWEBVIEW2_HOST_RESOURCE_ACCESS_KIND
+ {
+ COREWEBVIEW2_HOST_RESOURCE_ACCESS_KIND_DENY = 0,
+ COREWEBVIEW2_HOST_RESOURCE_ACCESS_KIND_ALLOW = ( COREWEBVIEW2_HOST_RESOURCE_ACCESS_KIND_DENY + 1 ) ,
+ COREWEBVIEW2_HOST_RESOURCE_ACCESS_KIND_DENY_CORS = ( COREWEBVIEW2_HOST_RESOURCE_ACCESS_KIND_ALLOW + 1 )
+ } COREWEBVIEW2_HOST_RESOURCE_ACCESS_KIND;
+
+typedef /* [v1_enum] */
+enum COREWEBVIEW2_SCRIPT_DIALOG_KIND
+ {
+ COREWEBVIEW2_SCRIPT_DIALOG_KIND_ALERT = 0,
+ COREWEBVIEW2_SCRIPT_DIALOG_KIND_CONFIRM = ( COREWEBVIEW2_SCRIPT_DIALOG_KIND_ALERT + 1 ) ,
+ COREWEBVIEW2_SCRIPT_DIALOG_KIND_PROMPT = ( COREWEBVIEW2_SCRIPT_DIALOG_KIND_CONFIRM + 1 ) ,
+ COREWEBVIEW2_SCRIPT_DIALOG_KIND_BEFOREUNLOAD = ( COREWEBVIEW2_SCRIPT_DIALOG_KIND_PROMPT + 1 )
+ } COREWEBVIEW2_SCRIPT_DIALOG_KIND;
+
+typedef /* [v1_enum] */
+enum COREWEBVIEW2_PROCESS_FAILED_KIND
+ {
+ COREWEBVIEW2_PROCESS_FAILED_KIND_BROWSER_PROCESS_EXITED = 0,
+ COREWEBVIEW2_PROCESS_FAILED_KIND_RENDER_PROCESS_EXITED = ( COREWEBVIEW2_PROCESS_FAILED_KIND_BROWSER_PROCESS_EXITED + 1 ) ,
+ COREWEBVIEW2_PROCESS_FAILED_KIND_RENDER_PROCESS_UNRESPONSIVE = ( COREWEBVIEW2_PROCESS_FAILED_KIND_RENDER_PROCESS_EXITED + 1 ) ,
+ COREWEBVIEW2_PROCESS_FAILED_KIND_FRAME_RENDER_PROCESS_EXITED = ( COREWEBVIEW2_PROCESS_FAILED_KIND_RENDER_PROCESS_UNRESPONSIVE + 1 ) ,
+ COREWEBVIEW2_PROCESS_FAILED_KIND_UTILITY_PROCESS_EXITED = ( COREWEBVIEW2_PROCESS_FAILED_KIND_FRAME_RENDER_PROCESS_EXITED + 1 ) ,
+ COREWEBVIEW2_PROCESS_FAILED_KIND_SANDBOX_HELPER_PROCESS_EXITED = ( COREWEBVIEW2_PROCESS_FAILED_KIND_UTILITY_PROCESS_EXITED + 1 ) ,
+ COREWEBVIEW2_PROCESS_FAILED_KIND_GPU_PROCESS_EXITED = ( COREWEBVIEW2_PROCESS_FAILED_KIND_SANDBOX_HELPER_PROCESS_EXITED + 1 ) ,
+ COREWEBVIEW2_PROCESS_FAILED_KIND_PPAPI_PLUGIN_PROCESS_EXITED = ( COREWEBVIEW2_PROCESS_FAILED_KIND_GPU_PROCESS_EXITED + 1 ) ,
+ COREWEBVIEW2_PROCESS_FAILED_KIND_PPAPI_BROKER_PROCESS_EXITED = ( COREWEBVIEW2_PROCESS_FAILED_KIND_PPAPI_PLUGIN_PROCESS_EXITED + 1 ) ,
+ COREWEBVIEW2_PROCESS_FAILED_KIND_UNKNOWN_PROCESS_EXITED = ( COREWEBVIEW2_PROCESS_FAILED_KIND_PPAPI_BROKER_PROCESS_EXITED + 1 )
+ } COREWEBVIEW2_PROCESS_FAILED_KIND;
+
+typedef /* [v1_enum] */
+enum COREWEBVIEW2_PROCESS_FAILED_REASON
+ {
+ COREWEBVIEW2_PROCESS_FAILED_REASON_UNEXPECTED = 0,
+ COREWEBVIEW2_PROCESS_FAILED_REASON_UNRESPONSIVE = ( COREWEBVIEW2_PROCESS_FAILED_REASON_UNEXPECTED + 1 ) ,
+ COREWEBVIEW2_PROCESS_FAILED_REASON_TERMINATED = ( COREWEBVIEW2_PROCESS_FAILED_REASON_UNRESPONSIVE + 1 ) ,
+ COREWEBVIEW2_PROCESS_FAILED_REASON_CRASHED = ( COREWEBVIEW2_PROCESS_FAILED_REASON_TERMINATED + 1 ) ,
+ COREWEBVIEW2_PROCESS_FAILED_REASON_LAUNCH_FAILED = ( COREWEBVIEW2_PROCESS_FAILED_REASON_CRASHED + 1 ) ,
+ COREWEBVIEW2_PROCESS_FAILED_REASON_OUT_OF_MEMORY = ( COREWEBVIEW2_PROCESS_FAILED_REASON_LAUNCH_FAILED + 1 )
+ } COREWEBVIEW2_PROCESS_FAILED_REASON;
+
+typedef /* [v1_enum] */
+enum COREWEBVIEW2_PERMISSION_KIND
+ {
+ COREWEBVIEW2_PERMISSION_KIND_UNKNOWN_PERMISSION = 0,
+ COREWEBVIEW2_PERMISSION_KIND_MICROPHONE = ( COREWEBVIEW2_PERMISSION_KIND_UNKNOWN_PERMISSION + 1 ) ,
+ COREWEBVIEW2_PERMISSION_KIND_CAMERA = ( COREWEBVIEW2_PERMISSION_KIND_MICROPHONE + 1 ) ,
+ COREWEBVIEW2_PERMISSION_KIND_GEOLOCATION = ( COREWEBVIEW2_PERMISSION_KIND_CAMERA + 1 ) ,
+ COREWEBVIEW2_PERMISSION_KIND_NOTIFICATIONS = ( COREWEBVIEW2_PERMISSION_KIND_GEOLOCATION + 1 ) ,
+ COREWEBVIEW2_PERMISSION_KIND_OTHER_SENSORS = ( COREWEBVIEW2_PERMISSION_KIND_NOTIFICATIONS + 1 ) ,
+ COREWEBVIEW2_PERMISSION_KIND_CLIPBOARD_READ = ( COREWEBVIEW2_PERMISSION_KIND_OTHER_SENSORS + 1 )
+ } COREWEBVIEW2_PERMISSION_KIND;
+
+typedef /* [v1_enum] */
+enum COREWEBVIEW2_PERMISSION_STATE
+ {
+ COREWEBVIEW2_PERMISSION_STATE_DEFAULT = 0,
+ COREWEBVIEW2_PERMISSION_STATE_ALLOW = ( COREWEBVIEW2_PERMISSION_STATE_DEFAULT + 1 ) ,
+ COREWEBVIEW2_PERMISSION_STATE_DENY = ( COREWEBVIEW2_PERMISSION_STATE_ALLOW + 1 )
+ } COREWEBVIEW2_PERMISSION_STATE;
+
+typedef /* [v1_enum] */
+enum COREWEBVIEW2_WEB_ERROR_STATUS
+ {
+ COREWEBVIEW2_WEB_ERROR_STATUS_UNKNOWN = 0,
+ COREWEBVIEW2_WEB_ERROR_STATUS_CERTIFICATE_COMMON_NAME_IS_INCORRECT = ( COREWEBVIEW2_WEB_ERROR_STATUS_UNKNOWN + 1 ) ,
+ COREWEBVIEW2_WEB_ERROR_STATUS_CERTIFICATE_EXPIRED = ( COREWEBVIEW2_WEB_ERROR_STATUS_CERTIFICATE_COMMON_NAME_IS_INCORRECT + 1 ) ,
+ COREWEBVIEW2_WEB_ERROR_STATUS_CLIENT_CERTIFICATE_CONTAINS_ERRORS = ( COREWEBVIEW2_WEB_ERROR_STATUS_CERTIFICATE_EXPIRED + 1 ) ,
+ COREWEBVIEW2_WEB_ERROR_STATUS_CERTIFICATE_REVOKED = ( COREWEBVIEW2_WEB_ERROR_STATUS_CLIENT_CERTIFICATE_CONTAINS_ERRORS + 1 ) ,
+ COREWEBVIEW2_WEB_ERROR_STATUS_CERTIFICATE_IS_INVALID = ( COREWEBVIEW2_WEB_ERROR_STATUS_CERTIFICATE_REVOKED + 1 ) ,
+ COREWEBVIEW2_WEB_ERROR_STATUS_SERVER_UNREACHABLE = ( COREWEBVIEW2_WEB_ERROR_STATUS_CERTIFICATE_IS_INVALID + 1 ) ,
+ COREWEBVIEW2_WEB_ERROR_STATUS_TIMEOUT = ( COREWEBVIEW2_WEB_ERROR_STATUS_SERVER_UNREACHABLE + 1 ) ,
+ COREWEBVIEW2_WEB_ERROR_STATUS_ERROR_HTTP_INVALID_SERVER_RESPONSE = ( COREWEBVIEW2_WEB_ERROR_STATUS_TIMEOUT + 1 ) ,
+ COREWEBVIEW2_WEB_ERROR_STATUS_CONNECTION_ABORTED = ( COREWEBVIEW2_WEB_ERROR_STATUS_ERROR_HTTP_INVALID_SERVER_RESPONSE + 1 ) ,
+ COREWEBVIEW2_WEB_ERROR_STATUS_CONNECTION_RESET = ( COREWEBVIEW2_WEB_ERROR_STATUS_CONNECTION_ABORTED + 1 ) ,
+ COREWEBVIEW2_WEB_ERROR_STATUS_DISCONNECTED = ( COREWEBVIEW2_WEB_ERROR_STATUS_CONNECTION_RESET + 1 ) ,
+ COREWEBVIEW2_WEB_ERROR_STATUS_CANNOT_CONNECT = ( COREWEBVIEW2_WEB_ERROR_STATUS_DISCONNECTED + 1 ) ,
+ COREWEBVIEW2_WEB_ERROR_STATUS_HOST_NAME_NOT_RESOLVED = ( COREWEBVIEW2_WEB_ERROR_STATUS_CANNOT_CONNECT + 1 ) ,
+ COREWEBVIEW2_WEB_ERROR_STATUS_OPERATION_CANCELED = ( COREWEBVIEW2_WEB_ERROR_STATUS_HOST_NAME_NOT_RESOLVED + 1 ) ,
+ COREWEBVIEW2_WEB_ERROR_STATUS_REDIRECT_FAILED = ( COREWEBVIEW2_WEB_ERROR_STATUS_OPERATION_CANCELED + 1 ) ,
+ COREWEBVIEW2_WEB_ERROR_STATUS_UNEXPECTED_ERROR = ( COREWEBVIEW2_WEB_ERROR_STATUS_REDIRECT_FAILED + 1 )
+ } COREWEBVIEW2_WEB_ERROR_STATUS;
+
+typedef /* [v1_enum] */
+enum COREWEBVIEW2_WEB_RESOURCE_CONTEXT
+ {
+ COREWEBVIEW2_WEB_RESOURCE_CONTEXT_ALL = 0,
+ COREWEBVIEW2_WEB_RESOURCE_CONTEXT_DOCUMENT = ( COREWEBVIEW2_WEB_RESOURCE_CONTEXT_ALL + 1 ) ,
+ COREWEBVIEW2_WEB_RESOURCE_CONTEXT_STYLESHEET = ( COREWEBVIEW2_WEB_RESOURCE_CONTEXT_DOCUMENT + 1 ) ,
+ COREWEBVIEW2_WEB_RESOURCE_CONTEXT_IMAGE = ( COREWEBVIEW2_WEB_RESOURCE_CONTEXT_STYLESHEET + 1 ) ,
+ COREWEBVIEW2_WEB_RESOURCE_CONTEXT_MEDIA = ( COREWEBVIEW2_WEB_RESOURCE_CONTEXT_IMAGE + 1 ) ,
+ COREWEBVIEW2_WEB_RESOURCE_CONTEXT_FONT = ( COREWEBVIEW2_WEB_RESOURCE_CONTEXT_MEDIA + 1 ) ,
+ COREWEBVIEW2_WEB_RESOURCE_CONTEXT_SCRIPT = ( COREWEBVIEW2_WEB_RESOURCE_CONTEXT_FONT + 1 ) ,
+ COREWEBVIEW2_WEB_RESOURCE_CONTEXT_XML_HTTP_REQUEST = ( COREWEBVIEW2_WEB_RESOURCE_CONTEXT_SCRIPT + 1 ) ,
+ COREWEBVIEW2_WEB_RESOURCE_CONTEXT_FETCH = ( COREWEBVIEW2_WEB_RESOURCE_CONTEXT_XML_HTTP_REQUEST + 1 ) ,
+ COREWEBVIEW2_WEB_RESOURCE_CONTEXT_TEXT_TRACK = ( COREWEBVIEW2_WEB_RESOURCE_CONTEXT_FETCH + 1 ) ,
+ COREWEBVIEW2_WEB_RESOURCE_CONTEXT_EVENT_SOURCE = ( COREWEBVIEW2_WEB_RESOURCE_CONTEXT_TEXT_TRACK + 1 ) ,
+ COREWEBVIEW2_WEB_RESOURCE_CONTEXT_WEBSOCKET = ( COREWEBVIEW2_WEB_RESOURCE_CONTEXT_EVENT_SOURCE + 1 ) ,
+ COREWEBVIEW2_WEB_RESOURCE_CONTEXT_MANIFEST = ( COREWEBVIEW2_WEB_RESOURCE_CONTEXT_WEBSOCKET + 1 ) ,
+ COREWEBVIEW2_WEB_RESOURCE_CONTEXT_SIGNED_EXCHANGE = ( COREWEBVIEW2_WEB_RESOURCE_CONTEXT_MANIFEST + 1 ) ,
+ COREWEBVIEW2_WEB_RESOURCE_CONTEXT_PING = ( COREWEBVIEW2_WEB_RESOURCE_CONTEXT_SIGNED_EXCHANGE + 1 ) ,
+ COREWEBVIEW2_WEB_RESOURCE_CONTEXT_CSP_VIOLATION_REPORT = ( COREWEBVIEW2_WEB_RESOURCE_CONTEXT_PING + 1 ) ,
+ COREWEBVIEW2_WEB_RESOURCE_CONTEXT_OTHER = ( COREWEBVIEW2_WEB_RESOURCE_CONTEXT_CSP_VIOLATION_REPORT + 1 )
+ } COREWEBVIEW2_WEB_RESOURCE_CONTEXT;
+
+typedef /* [v1_enum] */
+enum COREWEBVIEW2_MOVE_FOCUS_REASON
+ {
+ COREWEBVIEW2_MOVE_FOCUS_REASON_PROGRAMMATIC = 0,
+ COREWEBVIEW2_MOVE_FOCUS_REASON_NEXT = ( COREWEBVIEW2_MOVE_FOCUS_REASON_PROGRAMMATIC + 1 ) ,
+ COREWEBVIEW2_MOVE_FOCUS_REASON_PREVIOUS = ( COREWEBVIEW2_MOVE_FOCUS_REASON_NEXT + 1 )
+ } COREWEBVIEW2_MOVE_FOCUS_REASON;
+
+typedef /* [v1_enum] */
+enum COREWEBVIEW2_KEY_EVENT_KIND
+ {
+ COREWEBVIEW2_KEY_EVENT_KIND_KEY_DOWN = 0,
+ COREWEBVIEW2_KEY_EVENT_KIND_KEY_UP = ( COREWEBVIEW2_KEY_EVENT_KIND_KEY_DOWN + 1 ) ,
+ COREWEBVIEW2_KEY_EVENT_KIND_SYSTEM_KEY_DOWN = ( COREWEBVIEW2_KEY_EVENT_KIND_KEY_UP + 1 ) ,
+ COREWEBVIEW2_KEY_EVENT_KIND_SYSTEM_KEY_UP = ( COREWEBVIEW2_KEY_EVENT_KIND_SYSTEM_KEY_DOWN + 1 )
+ } COREWEBVIEW2_KEY_EVENT_KIND;
+
+typedef struct COREWEBVIEW2_PHYSICAL_KEY_STATUS
+ {
+ UINT32 RepeatCount;
+ UINT32 ScanCode;
+ BOOL IsExtendedKey;
+ BOOL IsMenuKeyDown;
+ BOOL WasKeyDown;
+ BOOL IsKeyReleased;
+ } COREWEBVIEW2_PHYSICAL_KEY_STATUS;
+
+typedef struct COREWEBVIEW2_COLOR
+ {
+ BYTE A;
+ BYTE R;
+ BYTE G;
+ BYTE B;
+ } COREWEBVIEW2_COLOR;
+
+typedef /* [v1_enum] */
+enum COREWEBVIEW2_MOUSE_EVENT_KIND
+ {
+ COREWEBVIEW2_MOUSE_EVENT_KIND_HORIZONTAL_WHEEL = 0x20e,
+ COREWEBVIEW2_MOUSE_EVENT_KIND_LEFT_BUTTON_DOUBLE_CLICK = 0x203,
+ COREWEBVIEW2_MOUSE_EVENT_KIND_LEFT_BUTTON_DOWN = 0x201,
+ COREWEBVIEW2_MOUSE_EVENT_KIND_LEFT_BUTTON_UP = 0x202,
+ COREWEBVIEW2_MOUSE_EVENT_KIND_LEAVE = 0x2a3,
+ COREWEBVIEW2_MOUSE_EVENT_KIND_MIDDLE_BUTTON_DOUBLE_CLICK = 0x209,
+ COREWEBVIEW2_MOUSE_EVENT_KIND_MIDDLE_BUTTON_DOWN = 0x207,
+ COREWEBVIEW2_MOUSE_EVENT_KIND_MIDDLE_BUTTON_UP = 0x208,
+ COREWEBVIEW2_MOUSE_EVENT_KIND_MOVE = 0x200,
+ COREWEBVIEW2_MOUSE_EVENT_KIND_RIGHT_BUTTON_DOUBLE_CLICK = 0x206,
+ COREWEBVIEW2_MOUSE_EVENT_KIND_RIGHT_BUTTON_DOWN = 0x204,
+ COREWEBVIEW2_MOUSE_EVENT_KIND_RIGHT_BUTTON_UP = 0x205,
+ COREWEBVIEW2_MOUSE_EVENT_KIND_WHEEL = 0x20a,
+ COREWEBVIEW2_MOUSE_EVENT_KIND_X_BUTTON_DOUBLE_CLICK = 0x20d,
+ COREWEBVIEW2_MOUSE_EVENT_KIND_X_BUTTON_DOWN = 0x20b,
+ COREWEBVIEW2_MOUSE_EVENT_KIND_X_BUTTON_UP = 0x20c
+ } COREWEBVIEW2_MOUSE_EVENT_KIND;
+
+typedef /* [v1_enum] */
+enum COREWEBVIEW2_MOUSE_EVENT_VIRTUAL_KEYS
+ {
+ COREWEBVIEW2_MOUSE_EVENT_VIRTUAL_KEYS_NONE = 0,
+ COREWEBVIEW2_MOUSE_EVENT_VIRTUAL_KEYS_LEFT_BUTTON = 0x1,
+ COREWEBVIEW2_MOUSE_EVENT_VIRTUAL_KEYS_RIGHT_BUTTON = 0x2,
+ COREWEBVIEW2_MOUSE_EVENT_VIRTUAL_KEYS_SHIFT = 0x4,
+ COREWEBVIEW2_MOUSE_EVENT_VIRTUAL_KEYS_CONTROL = 0x8,
+ COREWEBVIEW2_MOUSE_EVENT_VIRTUAL_KEYS_MIDDLE_BUTTON = 0x10,
+ COREWEBVIEW2_MOUSE_EVENT_VIRTUAL_KEYS_X_BUTTON1 = 0x20,
+ COREWEBVIEW2_MOUSE_EVENT_VIRTUAL_KEYS_X_BUTTON2 = 0x40
+ } COREWEBVIEW2_MOUSE_EVENT_VIRTUAL_KEYS;
+
+DEFINE_ENUM_FLAG_OPERATORS(COREWEBVIEW2_MOUSE_EVENT_VIRTUAL_KEYS);
+typedef /* [v1_enum] */
+enum COREWEBVIEW2_POINTER_EVENT_KIND
+ {
+ COREWEBVIEW2_POINTER_EVENT_KIND_ACTIVATE = 0x24b,
+ COREWEBVIEW2_POINTER_EVENT_KIND_DOWN = 0x246,
+ COREWEBVIEW2_POINTER_EVENT_KIND_ENTER = 0x249,
+ COREWEBVIEW2_POINTER_EVENT_KIND_LEAVE = 0x24a,
+ COREWEBVIEW2_POINTER_EVENT_KIND_UP = 0x247,
+ COREWEBVIEW2_POINTER_EVENT_KIND_UPDATE = 0x245
+ } COREWEBVIEW2_POINTER_EVENT_KIND;
+
+typedef /* [v1_enum] */
+enum COREWEBVIEW2_BOUNDS_MODE
+ {
+ COREWEBVIEW2_BOUNDS_MODE_USE_RAW_PIXELS = 0,
+ COREWEBVIEW2_BOUNDS_MODE_USE_RASTERIZATION_SCALE = ( COREWEBVIEW2_BOUNDS_MODE_USE_RAW_PIXELS + 1 )
+ } COREWEBVIEW2_BOUNDS_MODE;
+
+STDAPI CreateCoreWebView2EnvironmentWithOptions(PCWSTR browserExecutableFolder, PCWSTR userDataFolder, ICoreWebView2EnvironmentOptions* environmentOptions, ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler* environmentCreatedHandler);
+STDAPI CreateCoreWebView2Environment(ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler* environmentCreatedHandler);
+STDAPI GetAvailableCoreWebView2BrowserVersionString(PCWSTR browserExecutableFolder, LPWSTR* versionInfo);
+STDAPI CompareBrowserVersions(PCWSTR version1, PCWSTR version2, int* result);
+
+EXTERN_C const IID LIBID_WebView2;
+
+#ifndef __ICoreWebView2AcceleratorKeyPressedEventArgs_INTERFACE_DEFINED__
+#define __ICoreWebView2AcceleratorKeyPressedEventArgs_INTERFACE_DEFINED__
+
+/* interface ICoreWebView2AcceleratorKeyPressedEventArgs */
+/* [unique][object][uuid] */
+
+
+EXTERN_C __declspec(selectany) const IID IID_ICoreWebView2AcceleratorKeyPressedEventArgs = {0x9f760f8a,0xfb79,0x42be,{0x99,0x90,0x7b,0x56,0x90,0x0f,0xa9,0xc7}};
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("9f760f8a-fb79-42be-9990-7b56900fa9c7")
+ ICoreWebView2AcceleratorKeyPressedEventArgs : public IUnknown
+ {
+ public:
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_KeyEventKind(
+ /* [retval][out] */ COREWEBVIEW2_KEY_EVENT_KIND *keyEventKind) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_VirtualKey(
+ /* [retval][out] */ UINT *virtualKey) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_KeyEventLParam(
+ /* [retval][out] */ INT *lParam) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_PhysicalKeyStatus(
+ /* [retval][out] */ COREWEBVIEW2_PHYSICAL_KEY_STATUS *physicalKeyStatus) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_Handled(
+ /* [retval][out] */ BOOL *handled) = 0;
+
+ virtual /* [propput] */ HRESULT STDMETHODCALLTYPE put_Handled(
+ /* [in] */ BOOL handled) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct ICoreWebView2AcceleratorKeyPressedEventArgsVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ ICoreWebView2AcceleratorKeyPressedEventArgs * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ ICoreWebView2AcceleratorKeyPressedEventArgs * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ ICoreWebView2AcceleratorKeyPressedEventArgs * This);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_KeyEventKind )(
+ ICoreWebView2AcceleratorKeyPressedEventArgs * This,
+ /* [retval][out] */ COREWEBVIEW2_KEY_EVENT_KIND *keyEventKind);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_VirtualKey )(
+ ICoreWebView2AcceleratorKeyPressedEventArgs * This,
+ /* [retval][out] */ UINT *virtualKey);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_KeyEventLParam )(
+ ICoreWebView2AcceleratorKeyPressedEventArgs * This,
+ /* [retval][out] */ INT *lParam);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_PhysicalKeyStatus )(
+ ICoreWebView2AcceleratorKeyPressedEventArgs * This,
+ /* [retval][out] */ COREWEBVIEW2_PHYSICAL_KEY_STATUS *physicalKeyStatus);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_Handled )(
+ ICoreWebView2AcceleratorKeyPressedEventArgs * This,
+ /* [retval][out] */ BOOL *handled);
+
+ /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_Handled )(
+ ICoreWebView2AcceleratorKeyPressedEventArgs * This,
+ /* [in] */ BOOL handled);
+
+ END_INTERFACE
+ } ICoreWebView2AcceleratorKeyPressedEventArgsVtbl;
+
+ interface ICoreWebView2AcceleratorKeyPressedEventArgs
+ {
+ CONST_VTBL struct ICoreWebView2AcceleratorKeyPressedEventArgsVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define ICoreWebView2AcceleratorKeyPressedEventArgs_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define ICoreWebView2AcceleratorKeyPressedEventArgs_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define ICoreWebView2AcceleratorKeyPressedEventArgs_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define ICoreWebView2AcceleratorKeyPressedEventArgs_get_KeyEventKind(This,keyEventKind) \
+ ( (This)->lpVtbl -> get_KeyEventKind(This,keyEventKind) )
+
+#define ICoreWebView2AcceleratorKeyPressedEventArgs_get_VirtualKey(This,virtualKey) \
+ ( (This)->lpVtbl -> get_VirtualKey(This,virtualKey) )
+
+#define ICoreWebView2AcceleratorKeyPressedEventArgs_get_KeyEventLParam(This,lParam) \
+ ( (This)->lpVtbl -> get_KeyEventLParam(This,lParam) )
+
+#define ICoreWebView2AcceleratorKeyPressedEventArgs_get_PhysicalKeyStatus(This,physicalKeyStatus) \
+ ( (This)->lpVtbl -> get_PhysicalKeyStatus(This,physicalKeyStatus) )
+
+#define ICoreWebView2AcceleratorKeyPressedEventArgs_get_Handled(This,handled) \
+ ( (This)->lpVtbl -> get_Handled(This,handled) )
+
+#define ICoreWebView2AcceleratorKeyPressedEventArgs_put_Handled(This,handled) \
+ ( (This)->lpVtbl -> put_Handled(This,handled) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __ICoreWebView2AcceleratorKeyPressedEventArgs_INTERFACE_DEFINED__ */
+
+
+#ifndef __ICoreWebView2AcceleratorKeyPressedEventHandler_INTERFACE_DEFINED__
+#define __ICoreWebView2AcceleratorKeyPressedEventHandler_INTERFACE_DEFINED__
+
+/* interface ICoreWebView2AcceleratorKeyPressedEventHandler */
+/* [unique][object][uuid] */
+
+
+EXTERN_C __declspec(selectany) const IID IID_ICoreWebView2AcceleratorKeyPressedEventHandler = {0xb29c7e28,0xfa79,0x41a8,{0x8e,0x44,0x65,0x81,0x1c,0x76,0xdc,0xb2}};
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("b29c7e28-fa79-41a8-8e44-65811c76dcb2")
+ ICoreWebView2AcceleratorKeyPressedEventHandler : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE Invoke(
+ /* [in] */ ICoreWebView2Controller *sender,
+ /* [in] */ ICoreWebView2AcceleratorKeyPressedEventArgs *args) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct ICoreWebView2AcceleratorKeyPressedEventHandlerVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ ICoreWebView2AcceleratorKeyPressedEventHandler * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ ICoreWebView2AcceleratorKeyPressedEventHandler * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ ICoreWebView2AcceleratorKeyPressedEventHandler * This);
+
+ HRESULT ( STDMETHODCALLTYPE *Invoke )(
+ ICoreWebView2AcceleratorKeyPressedEventHandler * This,
+ /* [in] */ ICoreWebView2Controller *sender,
+ /* [in] */ ICoreWebView2AcceleratorKeyPressedEventArgs *args);
+
+ END_INTERFACE
+ } ICoreWebView2AcceleratorKeyPressedEventHandlerVtbl;
+
+ interface ICoreWebView2AcceleratorKeyPressedEventHandler
+ {
+ CONST_VTBL struct ICoreWebView2AcceleratorKeyPressedEventHandlerVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define ICoreWebView2AcceleratorKeyPressedEventHandler_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define ICoreWebView2AcceleratorKeyPressedEventHandler_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define ICoreWebView2AcceleratorKeyPressedEventHandler_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define ICoreWebView2AcceleratorKeyPressedEventHandler_Invoke(This,sender,args) \
+ ( (This)->lpVtbl -> Invoke(This,sender,args) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __ICoreWebView2AcceleratorKeyPressedEventHandler_INTERFACE_DEFINED__ */
+
+
+#ifndef __ICoreWebView2AddScriptToExecuteOnDocumentCreatedCompletedHandler_INTERFACE_DEFINED__
+#define __ICoreWebView2AddScriptToExecuteOnDocumentCreatedCompletedHandler_INTERFACE_DEFINED__
+
+/* interface ICoreWebView2AddScriptToExecuteOnDocumentCreatedCompletedHandler */
+/* [unique][object][uuid] */
+
+
+EXTERN_C __declspec(selectany) const IID IID_ICoreWebView2AddScriptToExecuteOnDocumentCreatedCompletedHandler = {0xb99369f3,0x9b11,0x47b5,{0xbc,0x6f,0x8e,0x78,0x95,0xfc,0xea,0x17}};
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("b99369f3-9b11-47b5-bc6f-8e7895fcea17")
+ ICoreWebView2AddScriptToExecuteOnDocumentCreatedCompletedHandler : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE Invoke(
+ /* [in] */ HRESULT errorCode,
+ /* [in] */ LPCWSTR id) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct ICoreWebView2AddScriptToExecuteOnDocumentCreatedCompletedHandlerVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ ICoreWebView2AddScriptToExecuteOnDocumentCreatedCompletedHandler * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ ICoreWebView2AddScriptToExecuteOnDocumentCreatedCompletedHandler * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ ICoreWebView2AddScriptToExecuteOnDocumentCreatedCompletedHandler * This);
+
+ HRESULT ( STDMETHODCALLTYPE *Invoke )(
+ ICoreWebView2AddScriptToExecuteOnDocumentCreatedCompletedHandler * This,
+ /* [in] */ HRESULT errorCode,
+ /* [in] */ LPCWSTR id);
+
+ END_INTERFACE
+ } ICoreWebView2AddScriptToExecuteOnDocumentCreatedCompletedHandlerVtbl;
+
+ interface ICoreWebView2AddScriptToExecuteOnDocumentCreatedCompletedHandler
+ {
+ CONST_VTBL struct ICoreWebView2AddScriptToExecuteOnDocumentCreatedCompletedHandlerVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define ICoreWebView2AddScriptToExecuteOnDocumentCreatedCompletedHandler_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define ICoreWebView2AddScriptToExecuteOnDocumentCreatedCompletedHandler_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define ICoreWebView2AddScriptToExecuteOnDocumentCreatedCompletedHandler_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define ICoreWebView2AddScriptToExecuteOnDocumentCreatedCompletedHandler_Invoke(This,errorCode,id) \
+ ( (This)->lpVtbl -> Invoke(This,errorCode,id) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __ICoreWebView2AddScriptToExecuteOnDocumentCreatedCompletedHandler_INTERFACE_DEFINED__ */
+
+
+#ifndef __ICoreWebView2CallDevToolsProtocolMethodCompletedHandler_INTERFACE_DEFINED__
+#define __ICoreWebView2CallDevToolsProtocolMethodCompletedHandler_INTERFACE_DEFINED__
+
+/* interface ICoreWebView2CallDevToolsProtocolMethodCompletedHandler */
+/* [unique][object][uuid] */
+
+
+EXTERN_C __declspec(selectany) const IID IID_ICoreWebView2CallDevToolsProtocolMethodCompletedHandler = {0x5c4889f0,0x5ef6,0x4c5a,{0x95,0x2c,0xd8,0xf1,0xb9,0x2d,0x05,0x74}};
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("5c4889f0-5ef6-4c5a-952c-d8f1b92d0574")
+ ICoreWebView2CallDevToolsProtocolMethodCompletedHandler : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE Invoke(
+ /* [in] */ HRESULT errorCode,
+ /* [in] */ LPCWSTR returnObjectAsJson) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct ICoreWebView2CallDevToolsProtocolMethodCompletedHandlerVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ ICoreWebView2CallDevToolsProtocolMethodCompletedHandler * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ ICoreWebView2CallDevToolsProtocolMethodCompletedHandler * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ ICoreWebView2CallDevToolsProtocolMethodCompletedHandler * This);
+
+ HRESULT ( STDMETHODCALLTYPE *Invoke )(
+ ICoreWebView2CallDevToolsProtocolMethodCompletedHandler * This,
+ /* [in] */ HRESULT errorCode,
+ /* [in] */ LPCWSTR returnObjectAsJson);
+
+ END_INTERFACE
+ } ICoreWebView2CallDevToolsProtocolMethodCompletedHandlerVtbl;
+
+ interface ICoreWebView2CallDevToolsProtocolMethodCompletedHandler
+ {
+ CONST_VTBL struct ICoreWebView2CallDevToolsProtocolMethodCompletedHandlerVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define ICoreWebView2CallDevToolsProtocolMethodCompletedHandler_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define ICoreWebView2CallDevToolsProtocolMethodCompletedHandler_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define ICoreWebView2CallDevToolsProtocolMethodCompletedHandler_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define ICoreWebView2CallDevToolsProtocolMethodCompletedHandler_Invoke(This,errorCode,returnObjectAsJson) \
+ ( (This)->lpVtbl -> Invoke(This,errorCode,returnObjectAsJson) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __ICoreWebView2CallDevToolsProtocolMethodCompletedHandler_INTERFACE_DEFINED__ */
+
+
+#ifndef __ICoreWebView2CapturePreviewCompletedHandler_INTERFACE_DEFINED__
+#define __ICoreWebView2CapturePreviewCompletedHandler_INTERFACE_DEFINED__
+
+/* interface ICoreWebView2CapturePreviewCompletedHandler */
+/* [unique][object][uuid] */
+
+
+EXTERN_C __declspec(selectany) const IID IID_ICoreWebView2CapturePreviewCompletedHandler = {0x697e05e9,0x3d8f,0x45fa,{0x96,0xf4,0x8f,0xfe,0x1e,0xde,0xda,0xf5}};
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("697e05e9-3d8f-45fa-96f4-8ffe1ededaf5")
+ ICoreWebView2CapturePreviewCompletedHandler : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE Invoke(
+ /* [in] */ HRESULT errorCode) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct ICoreWebView2CapturePreviewCompletedHandlerVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ ICoreWebView2CapturePreviewCompletedHandler * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ ICoreWebView2CapturePreviewCompletedHandler * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ ICoreWebView2CapturePreviewCompletedHandler * This);
+
+ HRESULT ( STDMETHODCALLTYPE *Invoke )(
+ ICoreWebView2CapturePreviewCompletedHandler * This,
+ /* [in] */ HRESULT errorCode);
+
+ END_INTERFACE
+ } ICoreWebView2CapturePreviewCompletedHandlerVtbl;
+
+ interface ICoreWebView2CapturePreviewCompletedHandler
+ {
+ CONST_VTBL struct ICoreWebView2CapturePreviewCompletedHandlerVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define ICoreWebView2CapturePreviewCompletedHandler_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define ICoreWebView2CapturePreviewCompletedHandler_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define ICoreWebView2CapturePreviewCompletedHandler_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define ICoreWebView2CapturePreviewCompletedHandler_Invoke(This,errorCode) \
+ ( (This)->lpVtbl -> Invoke(This,errorCode) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __ICoreWebView2CapturePreviewCompletedHandler_INTERFACE_DEFINED__ */
+
+
+#ifndef __ICoreWebView2_INTERFACE_DEFINED__
+#define __ICoreWebView2_INTERFACE_DEFINED__
+
+/* interface ICoreWebView2 */
+/* [unique][object][uuid] */
+
+
+EXTERN_C __declspec(selectany) const IID IID_ICoreWebView2 = {0x76eceacb,0x0462,0x4d94,{0xac,0x83,0x42,0x3a,0x67,0x93,0x77,0x5e}};
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("76eceacb-0462-4d94-ac83-423a6793775e")
+ ICoreWebView2 : public IUnknown
+ {
+ public:
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_Settings(
+ /* [retval][out] */ ICoreWebView2Settings **settings) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_Source(
+ /* [retval][out] */ LPWSTR *uri) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE Navigate(
+ /* [in] */ LPCWSTR uri) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE NavigateToString(
+ /* [in] */ LPCWSTR htmlContent) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE add_NavigationStarting(
+ /* [in] */ ICoreWebView2NavigationStartingEventHandler *eventHandler,
+ /* [out] */ EventRegistrationToken *token) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE remove_NavigationStarting(
+ /* [in] */ EventRegistrationToken token) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE add_ContentLoading(
+ /* [in] */ ICoreWebView2ContentLoadingEventHandler *eventHandler,
+ /* [out] */ EventRegistrationToken *token) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE remove_ContentLoading(
+ /* [in] */ EventRegistrationToken token) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE add_SourceChanged(
+ /* [in] */ ICoreWebView2SourceChangedEventHandler *eventHandler,
+ /* [out] */ EventRegistrationToken *token) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE remove_SourceChanged(
+ /* [in] */ EventRegistrationToken token) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE add_HistoryChanged(
+ /* [in] */ ICoreWebView2HistoryChangedEventHandler *eventHandler,
+ /* [out] */ EventRegistrationToken *token) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE remove_HistoryChanged(
+ /* [in] */ EventRegistrationToken token) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE add_NavigationCompleted(
+ /* [in] */ ICoreWebView2NavigationCompletedEventHandler *eventHandler,
+ /* [out] */ EventRegistrationToken *token) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE remove_NavigationCompleted(
+ /* [in] */ EventRegistrationToken token) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE add_FrameNavigationStarting(
+ /* [in] */ ICoreWebView2NavigationStartingEventHandler *eventHandler,
+ /* [out] */ EventRegistrationToken *token) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE remove_FrameNavigationStarting(
+ /* [in] */ EventRegistrationToken token) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE add_FrameNavigationCompleted(
+ /* [in] */ ICoreWebView2NavigationCompletedEventHandler *eventHandler,
+ /* [out] */ EventRegistrationToken *token) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE remove_FrameNavigationCompleted(
+ /* [in] */ EventRegistrationToken token) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE add_ScriptDialogOpening(
+ /* [in] */ ICoreWebView2ScriptDialogOpeningEventHandler *eventHandler,
+ /* [out] */ EventRegistrationToken *token) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE remove_ScriptDialogOpening(
+ /* [in] */ EventRegistrationToken token) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE add_PermissionRequested(
+ /* [in] */ ICoreWebView2PermissionRequestedEventHandler *eventHandler,
+ /* [out] */ EventRegistrationToken *token) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE remove_PermissionRequested(
+ /* [in] */ EventRegistrationToken token) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE add_ProcessFailed(
+ /* [in] */ ICoreWebView2ProcessFailedEventHandler *eventHandler,
+ /* [out] */ EventRegistrationToken *token) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE remove_ProcessFailed(
+ /* [in] */ EventRegistrationToken token) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE AddScriptToExecuteOnDocumentCreated(
+ /* [in] */ LPCWSTR javaScript,
+ /* [in] */ ICoreWebView2AddScriptToExecuteOnDocumentCreatedCompletedHandler *handler) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE RemoveScriptToExecuteOnDocumentCreated(
+ /* [in] */ LPCWSTR id) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE ExecuteScript(
+ /* [in] */ LPCWSTR javaScript,
+ /* [in] */ ICoreWebView2ExecuteScriptCompletedHandler *handler) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE CapturePreview(
+ /* [in] */ COREWEBVIEW2_CAPTURE_PREVIEW_IMAGE_FORMAT imageFormat,
+ /* [in] */ IStream *imageStream,
+ /* [in] */ ICoreWebView2CapturePreviewCompletedHandler *handler) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE Reload( void) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE PostWebMessageAsJson(
+ /* [in] */ LPCWSTR webMessageAsJson) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE PostWebMessageAsString(
+ /* [in] */ LPCWSTR webMessageAsString) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE add_WebMessageReceived(
+ /* [in] */ ICoreWebView2WebMessageReceivedEventHandler *handler,
+ /* [out] */ EventRegistrationToken *token) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE remove_WebMessageReceived(
+ /* [in] */ EventRegistrationToken token) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE CallDevToolsProtocolMethod(
+ /* [in] */ LPCWSTR methodName,
+ /* [in] */ LPCWSTR parametersAsJson,
+ /* [in] */ ICoreWebView2CallDevToolsProtocolMethodCompletedHandler *handler) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_BrowserProcessId(
+ /* [retval][out] */ UINT32 *value) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_CanGoBack(
+ /* [retval][out] */ BOOL *canGoBack) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_CanGoForward(
+ /* [retval][out] */ BOOL *canGoForward) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GoBack( void) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GoForward( void) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetDevToolsProtocolEventReceiver(
+ /* [in] */ LPCWSTR eventName,
+ /* [retval][out] */ ICoreWebView2DevToolsProtocolEventReceiver **receiver) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE Stop( void) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE add_NewWindowRequested(
+ /* [in] */ ICoreWebView2NewWindowRequestedEventHandler *eventHandler,
+ /* [out] */ EventRegistrationToken *token) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE remove_NewWindowRequested(
+ /* [in] */ EventRegistrationToken token) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE add_DocumentTitleChanged(
+ /* [in] */ ICoreWebView2DocumentTitleChangedEventHandler *eventHandler,
+ /* [out] */ EventRegistrationToken *token) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE remove_DocumentTitleChanged(
+ /* [in] */ EventRegistrationToken token) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_DocumentTitle(
+ /* [retval][out] */ LPWSTR *title) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE AddHostObjectToScript(
+ /* [in] */ LPCWSTR name,
+ /* [in] */ VARIANT *object) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE RemoveHostObjectFromScript(
+ /* [in] */ LPCWSTR name) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE OpenDevToolsWindow( void) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE add_ContainsFullScreenElementChanged(
+ /* [in] */ ICoreWebView2ContainsFullScreenElementChangedEventHandler *eventHandler,
+ /* [out] */ EventRegistrationToken *token) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE remove_ContainsFullScreenElementChanged(
+ /* [in] */ EventRegistrationToken token) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_ContainsFullScreenElement(
+ /* [retval][out] */ BOOL *containsFullScreenElement) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE add_WebResourceRequested(
+ /* [in] */ ICoreWebView2WebResourceRequestedEventHandler *eventHandler,
+ /* [out] */ EventRegistrationToken *token) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE remove_WebResourceRequested(
+ /* [in] */ EventRegistrationToken token) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE AddWebResourceRequestedFilter(
+ /* [in] */ const LPCWSTR uri,
+ /* [in] */ const COREWEBVIEW2_WEB_RESOURCE_CONTEXT resourceContext) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE RemoveWebResourceRequestedFilter(
+ /* [in] */ const LPCWSTR uri,
+ /* [in] */ const COREWEBVIEW2_WEB_RESOURCE_CONTEXT resourceContext) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE add_WindowCloseRequested(
+ /* [in] */ ICoreWebView2WindowCloseRequestedEventHandler *eventHandler,
+ /* [out] */ EventRegistrationToken *token) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE remove_WindowCloseRequested(
+ /* [in] */ EventRegistrationToken token) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct ICoreWebView2Vtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ ICoreWebView2 * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ ICoreWebView2 * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ ICoreWebView2 * This);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_Settings )(
+ ICoreWebView2 * This,
+ /* [retval][out] */ ICoreWebView2Settings **settings);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_Source )(
+ ICoreWebView2 * This,
+ /* [retval][out] */ LPWSTR *uri);
+
+ HRESULT ( STDMETHODCALLTYPE *Navigate )(
+ ICoreWebView2 * This,
+ /* [in] */ LPCWSTR uri);
+
+ HRESULT ( STDMETHODCALLTYPE *NavigateToString )(
+ ICoreWebView2 * This,
+ /* [in] */ LPCWSTR htmlContent);
+
+ HRESULT ( STDMETHODCALLTYPE *add_NavigationStarting )(
+ ICoreWebView2 * This,
+ /* [in] */ ICoreWebView2NavigationStartingEventHandler *eventHandler,
+ /* [out] */ EventRegistrationToken *token);
+
+ HRESULT ( STDMETHODCALLTYPE *remove_NavigationStarting )(
+ ICoreWebView2 * This,
+ /* [in] */ EventRegistrationToken token);
+
+ HRESULT ( STDMETHODCALLTYPE *add_ContentLoading )(
+ ICoreWebView2 * This,
+ /* [in] */ ICoreWebView2ContentLoadingEventHandler *eventHandler,
+ /* [out] */ EventRegistrationToken *token);
+
+ HRESULT ( STDMETHODCALLTYPE *remove_ContentLoading )(
+ ICoreWebView2 * This,
+ /* [in] */ EventRegistrationToken token);
+
+ HRESULT ( STDMETHODCALLTYPE *add_SourceChanged )(
+ ICoreWebView2 * This,
+ /* [in] */ ICoreWebView2SourceChangedEventHandler *eventHandler,
+ /* [out] */ EventRegistrationToken *token);
+
+ HRESULT ( STDMETHODCALLTYPE *remove_SourceChanged )(
+ ICoreWebView2 * This,
+ /* [in] */ EventRegistrationToken token);
+
+ HRESULT ( STDMETHODCALLTYPE *add_HistoryChanged )(
+ ICoreWebView2 * This,
+ /* [in] */ ICoreWebView2HistoryChangedEventHandler *eventHandler,
+ /* [out] */ EventRegistrationToken *token);
+
+ HRESULT ( STDMETHODCALLTYPE *remove_HistoryChanged )(
+ ICoreWebView2 * This,
+ /* [in] */ EventRegistrationToken token);
+
+ HRESULT ( STDMETHODCALLTYPE *add_NavigationCompleted )(
+ ICoreWebView2 * This,
+ /* [in] */ ICoreWebView2NavigationCompletedEventHandler *eventHandler,
+ /* [out] */ EventRegistrationToken *token);
+
+ HRESULT ( STDMETHODCALLTYPE *remove_NavigationCompleted )(
+ ICoreWebView2 * This,
+ /* [in] */ EventRegistrationToken token);
+
+ HRESULT ( STDMETHODCALLTYPE *add_FrameNavigationStarting )(
+ ICoreWebView2 * This,
+ /* [in] */ ICoreWebView2NavigationStartingEventHandler *eventHandler,
+ /* [out] */ EventRegistrationToken *token);
+
+ HRESULT ( STDMETHODCALLTYPE *remove_FrameNavigationStarting )(
+ ICoreWebView2 * This,
+ /* [in] */ EventRegistrationToken token);
+
+ HRESULT ( STDMETHODCALLTYPE *add_FrameNavigationCompleted )(
+ ICoreWebView2 * This,
+ /* [in] */ ICoreWebView2NavigationCompletedEventHandler *eventHandler,
+ /* [out] */ EventRegistrationToken *token);
+
+ HRESULT ( STDMETHODCALLTYPE *remove_FrameNavigationCompleted )(
+ ICoreWebView2 * This,
+ /* [in] */ EventRegistrationToken token);
+
+ HRESULT ( STDMETHODCALLTYPE *add_ScriptDialogOpening )(
+ ICoreWebView2 * This,
+ /* [in] */ ICoreWebView2ScriptDialogOpeningEventHandler *eventHandler,
+ /* [out] */ EventRegistrationToken *token);
+
+ HRESULT ( STDMETHODCALLTYPE *remove_ScriptDialogOpening )(
+ ICoreWebView2 * This,
+ /* [in] */ EventRegistrationToken token);
+
+ HRESULT ( STDMETHODCALLTYPE *add_PermissionRequested )(
+ ICoreWebView2 * This,
+ /* [in] */ ICoreWebView2PermissionRequestedEventHandler *eventHandler,
+ /* [out] */ EventRegistrationToken *token);
+
+ HRESULT ( STDMETHODCALLTYPE *remove_PermissionRequested )(
+ ICoreWebView2 * This,
+ /* [in] */ EventRegistrationToken token);
+
+ HRESULT ( STDMETHODCALLTYPE *add_ProcessFailed )(
+ ICoreWebView2 * This,
+ /* [in] */ ICoreWebView2ProcessFailedEventHandler *eventHandler,
+ /* [out] */ EventRegistrationToken *token);
+
+ HRESULT ( STDMETHODCALLTYPE *remove_ProcessFailed )(
+ ICoreWebView2 * This,
+ /* [in] */ EventRegistrationToken token);
+
+ HRESULT ( STDMETHODCALLTYPE *AddScriptToExecuteOnDocumentCreated )(
+ ICoreWebView2 * This,
+ /* [in] */ LPCWSTR javaScript,
+ /* [in] */ ICoreWebView2AddScriptToExecuteOnDocumentCreatedCompletedHandler *handler);
+
+ HRESULT ( STDMETHODCALLTYPE *RemoveScriptToExecuteOnDocumentCreated )(
+ ICoreWebView2 * This,
+ /* [in] */ LPCWSTR id);
+
+ HRESULT ( STDMETHODCALLTYPE *ExecuteScript )(
+ ICoreWebView2 * This,
+ /* [in] */ LPCWSTR javaScript,
+ /* [in] */ ICoreWebView2ExecuteScriptCompletedHandler *handler);
+
+ HRESULT ( STDMETHODCALLTYPE *CapturePreview )(
+ ICoreWebView2 * This,
+ /* [in] */ COREWEBVIEW2_CAPTURE_PREVIEW_IMAGE_FORMAT imageFormat,
+ /* [in] */ IStream *imageStream,
+ /* [in] */ ICoreWebView2CapturePreviewCompletedHandler *handler);
+
+ HRESULT ( STDMETHODCALLTYPE *Reload )(
+ ICoreWebView2 * This);
+
+ HRESULT ( STDMETHODCALLTYPE *PostWebMessageAsJson )(
+ ICoreWebView2 * This,
+ /* [in] */ LPCWSTR webMessageAsJson);
+
+ HRESULT ( STDMETHODCALLTYPE *PostWebMessageAsString )(
+ ICoreWebView2 * This,
+ /* [in] */ LPCWSTR webMessageAsString);
+
+ HRESULT ( STDMETHODCALLTYPE *add_WebMessageReceived )(
+ ICoreWebView2 * This,
+ /* [in] */ ICoreWebView2WebMessageReceivedEventHandler *handler,
+ /* [out] */ EventRegistrationToken *token);
+
+ HRESULT ( STDMETHODCALLTYPE *remove_WebMessageReceived )(
+ ICoreWebView2 * This,
+ /* [in] */ EventRegistrationToken token);
+
+ HRESULT ( STDMETHODCALLTYPE *CallDevToolsProtocolMethod )(
+ ICoreWebView2 * This,
+ /* [in] */ LPCWSTR methodName,
+ /* [in] */ LPCWSTR parametersAsJson,
+ /* [in] */ ICoreWebView2CallDevToolsProtocolMethodCompletedHandler *handler);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_BrowserProcessId )(
+ ICoreWebView2 * This,
+ /* [retval][out] */ UINT32 *value);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_CanGoBack )(
+ ICoreWebView2 * This,
+ /* [retval][out] */ BOOL *canGoBack);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_CanGoForward )(
+ ICoreWebView2 * This,
+ /* [retval][out] */ BOOL *canGoForward);
+
+ HRESULT ( STDMETHODCALLTYPE *GoBack )(
+ ICoreWebView2 * This);
+
+ HRESULT ( STDMETHODCALLTYPE *GoForward )(
+ ICoreWebView2 * This);
+
+ HRESULT ( STDMETHODCALLTYPE *GetDevToolsProtocolEventReceiver )(
+ ICoreWebView2 * This,
+ /* [in] */ LPCWSTR eventName,
+ /* [retval][out] */ ICoreWebView2DevToolsProtocolEventReceiver **receiver);
+
+ HRESULT ( STDMETHODCALLTYPE *Stop )(
+ ICoreWebView2 * This);
+
+ HRESULT ( STDMETHODCALLTYPE *add_NewWindowRequested )(
+ ICoreWebView2 * This,
+ /* [in] */ ICoreWebView2NewWindowRequestedEventHandler *eventHandler,
+ /* [out] */ EventRegistrationToken *token);
+
+ HRESULT ( STDMETHODCALLTYPE *remove_NewWindowRequested )(
+ ICoreWebView2 * This,
+ /* [in] */ EventRegistrationToken token);
+
+ HRESULT ( STDMETHODCALLTYPE *add_DocumentTitleChanged )(
+ ICoreWebView2 * This,
+ /* [in] */ ICoreWebView2DocumentTitleChangedEventHandler *eventHandler,
+ /* [out] */ EventRegistrationToken *token);
+
+ HRESULT ( STDMETHODCALLTYPE *remove_DocumentTitleChanged )(
+ ICoreWebView2 * This,
+ /* [in] */ EventRegistrationToken token);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_DocumentTitle )(
+ ICoreWebView2 * This,
+ /* [retval][out] */ LPWSTR *title);
+
+ HRESULT ( STDMETHODCALLTYPE *AddHostObjectToScript )(
+ ICoreWebView2 * This,
+ /* [in] */ LPCWSTR name,
+ /* [in] */ VARIANT *object);
+
+ HRESULT ( STDMETHODCALLTYPE *RemoveHostObjectFromScript )(
+ ICoreWebView2 * This,
+ /* [in] */ LPCWSTR name);
+
+ HRESULT ( STDMETHODCALLTYPE *OpenDevToolsWindow )(
+ ICoreWebView2 * This);
+
+ HRESULT ( STDMETHODCALLTYPE *add_ContainsFullScreenElementChanged )(
+ ICoreWebView2 * This,
+ /* [in] */ ICoreWebView2ContainsFullScreenElementChangedEventHandler *eventHandler,
+ /* [out] */ EventRegistrationToken *token);
+
+ HRESULT ( STDMETHODCALLTYPE *remove_ContainsFullScreenElementChanged )(
+ ICoreWebView2 * This,
+ /* [in] */ EventRegistrationToken token);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_ContainsFullScreenElement )(
+ ICoreWebView2 * This,
+ /* [retval][out] */ BOOL *containsFullScreenElement);
+
+ HRESULT ( STDMETHODCALLTYPE *add_WebResourceRequested )(
+ ICoreWebView2 * This,
+ /* [in] */ ICoreWebView2WebResourceRequestedEventHandler *eventHandler,
+ /* [out] */ EventRegistrationToken *token);
+
+ HRESULT ( STDMETHODCALLTYPE *remove_WebResourceRequested )(
+ ICoreWebView2 * This,
+ /* [in] */ EventRegistrationToken token);
+
+ HRESULT ( STDMETHODCALLTYPE *AddWebResourceRequestedFilter )(
+ ICoreWebView2 * This,
+ /* [in] */ const LPCWSTR uri,
+ /* [in] */ const COREWEBVIEW2_WEB_RESOURCE_CONTEXT resourceContext);
+
+ HRESULT ( STDMETHODCALLTYPE *RemoveWebResourceRequestedFilter )(
+ ICoreWebView2 * This,
+ /* [in] */ const LPCWSTR uri,
+ /* [in] */ const COREWEBVIEW2_WEB_RESOURCE_CONTEXT resourceContext);
+
+ HRESULT ( STDMETHODCALLTYPE *add_WindowCloseRequested )(
+ ICoreWebView2 * This,
+ /* [in] */ ICoreWebView2WindowCloseRequestedEventHandler *eventHandler,
+ /* [out] */ EventRegistrationToken *token);
+
+ HRESULT ( STDMETHODCALLTYPE *remove_WindowCloseRequested )(
+ ICoreWebView2 * This,
+ /* [in] */ EventRegistrationToken token);
+
+ END_INTERFACE
+ } ICoreWebView2Vtbl;
+
+ interface ICoreWebView2
+ {
+ CONST_VTBL struct ICoreWebView2Vtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define ICoreWebView2_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define ICoreWebView2_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define ICoreWebView2_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define ICoreWebView2_get_Settings(This,settings) \
+ ( (This)->lpVtbl -> get_Settings(This,settings) )
+
+#define ICoreWebView2_get_Source(This,uri) \
+ ( (This)->lpVtbl -> get_Source(This,uri) )
+
+#define ICoreWebView2_Navigate(This,uri) \
+ ( (This)->lpVtbl -> Navigate(This,uri) )
+
+#define ICoreWebView2_NavigateToString(This,htmlContent) \
+ ( (This)->lpVtbl -> NavigateToString(This,htmlContent) )
+
+#define ICoreWebView2_add_NavigationStarting(This,eventHandler,token) \
+ ( (This)->lpVtbl -> add_NavigationStarting(This,eventHandler,token) )
+
+#define ICoreWebView2_remove_NavigationStarting(This,token) \
+ ( (This)->lpVtbl -> remove_NavigationStarting(This,token) )
+
+#define ICoreWebView2_add_ContentLoading(This,eventHandler,token) \
+ ( (This)->lpVtbl -> add_ContentLoading(This,eventHandler,token) )
+
+#define ICoreWebView2_remove_ContentLoading(This,token) \
+ ( (This)->lpVtbl -> remove_ContentLoading(This,token) )
+
+#define ICoreWebView2_add_SourceChanged(This,eventHandler,token) \
+ ( (This)->lpVtbl -> add_SourceChanged(This,eventHandler,token) )
+
+#define ICoreWebView2_remove_SourceChanged(This,token) \
+ ( (This)->lpVtbl -> remove_SourceChanged(This,token) )
+
+#define ICoreWebView2_add_HistoryChanged(This,eventHandler,token) \
+ ( (This)->lpVtbl -> add_HistoryChanged(This,eventHandler,token) )
+
+#define ICoreWebView2_remove_HistoryChanged(This,token) \
+ ( (This)->lpVtbl -> remove_HistoryChanged(This,token) )
+
+#define ICoreWebView2_add_NavigationCompleted(This,eventHandler,token) \
+ ( (This)->lpVtbl -> add_NavigationCompleted(This,eventHandler,token) )
+
+#define ICoreWebView2_remove_NavigationCompleted(This,token) \
+ ( (This)->lpVtbl -> remove_NavigationCompleted(This,token) )
+
+#define ICoreWebView2_add_FrameNavigationStarting(This,eventHandler,token) \
+ ( (This)->lpVtbl -> add_FrameNavigationStarting(This,eventHandler,token) )
+
+#define ICoreWebView2_remove_FrameNavigationStarting(This,token) \
+ ( (This)->lpVtbl -> remove_FrameNavigationStarting(This,token) )
+
+#define ICoreWebView2_add_FrameNavigationCompleted(This,eventHandler,token) \
+ ( (This)->lpVtbl -> add_FrameNavigationCompleted(This,eventHandler,token) )
+
+#define ICoreWebView2_remove_FrameNavigationCompleted(This,token) \
+ ( (This)->lpVtbl -> remove_FrameNavigationCompleted(This,token) )
+
+#define ICoreWebView2_add_ScriptDialogOpening(This,eventHandler,token) \
+ ( (This)->lpVtbl -> add_ScriptDialogOpening(This,eventHandler,token) )
+
+#define ICoreWebView2_remove_ScriptDialogOpening(This,token) \
+ ( (This)->lpVtbl -> remove_ScriptDialogOpening(This,token) )
+
+#define ICoreWebView2_add_PermissionRequested(This,eventHandler,token) \
+ ( (This)->lpVtbl -> add_PermissionRequested(This,eventHandler,token) )
+
+#define ICoreWebView2_remove_PermissionRequested(This,token) \
+ ( (This)->lpVtbl -> remove_PermissionRequested(This,token) )
+
+#define ICoreWebView2_add_ProcessFailed(This,eventHandler,token) \
+ ( (This)->lpVtbl -> add_ProcessFailed(This,eventHandler,token) )
+
+#define ICoreWebView2_remove_ProcessFailed(This,token) \
+ ( (This)->lpVtbl -> remove_ProcessFailed(This,token) )
+
+#define ICoreWebView2_AddScriptToExecuteOnDocumentCreated(This,javaScript,handler) \
+ ( (This)->lpVtbl -> AddScriptToExecuteOnDocumentCreated(This,javaScript,handler) )
+
+#define ICoreWebView2_RemoveScriptToExecuteOnDocumentCreated(This,id) \
+ ( (This)->lpVtbl -> RemoveScriptToExecuteOnDocumentCreated(This,id) )
+
+#define ICoreWebView2_ExecuteScript(This,javaScript,handler) \
+ ( (This)->lpVtbl -> ExecuteScript(This,javaScript,handler) )
+
+#define ICoreWebView2_CapturePreview(This,imageFormat,imageStream,handler) \
+ ( (This)->lpVtbl -> CapturePreview(This,imageFormat,imageStream,handler) )
+
+#define ICoreWebView2_Reload(This) \
+ ( (This)->lpVtbl -> Reload(This) )
+
+#define ICoreWebView2_PostWebMessageAsJson(This,webMessageAsJson) \
+ ( (This)->lpVtbl -> PostWebMessageAsJson(This,webMessageAsJson) )
+
+#define ICoreWebView2_PostWebMessageAsString(This,webMessageAsString) \
+ ( (This)->lpVtbl -> PostWebMessageAsString(This,webMessageAsString) )
+
+#define ICoreWebView2_add_WebMessageReceived(This,handler,token) \
+ ( (This)->lpVtbl -> add_WebMessageReceived(This,handler,token) )
+
+#define ICoreWebView2_remove_WebMessageReceived(This,token) \
+ ( (This)->lpVtbl -> remove_WebMessageReceived(This,token) )
+
+#define ICoreWebView2_CallDevToolsProtocolMethod(This,methodName,parametersAsJson,handler) \
+ ( (This)->lpVtbl -> CallDevToolsProtocolMethod(This,methodName,parametersAsJson,handler) )
+
+#define ICoreWebView2_get_BrowserProcessId(This,value) \
+ ( (This)->lpVtbl -> get_BrowserProcessId(This,value) )
+
+#define ICoreWebView2_get_CanGoBack(This,canGoBack) \
+ ( (This)->lpVtbl -> get_CanGoBack(This,canGoBack) )
+
+#define ICoreWebView2_get_CanGoForward(This,canGoForward) \
+ ( (This)->lpVtbl -> get_CanGoForward(This,canGoForward) )
+
+#define ICoreWebView2_GoBack(This) \
+ ( (This)->lpVtbl -> GoBack(This) )
+
+#define ICoreWebView2_GoForward(This) \
+ ( (This)->lpVtbl -> GoForward(This) )
+
+#define ICoreWebView2_GetDevToolsProtocolEventReceiver(This,eventName,receiver) \
+ ( (This)->lpVtbl -> GetDevToolsProtocolEventReceiver(This,eventName,receiver) )
+
+#define ICoreWebView2_Stop(This) \
+ ( (This)->lpVtbl -> Stop(This) )
+
+#define ICoreWebView2_add_NewWindowRequested(This,eventHandler,token) \
+ ( (This)->lpVtbl -> add_NewWindowRequested(This,eventHandler,token) )
+
+#define ICoreWebView2_remove_NewWindowRequested(This,token) \
+ ( (This)->lpVtbl -> remove_NewWindowRequested(This,token) )
+
+#define ICoreWebView2_add_DocumentTitleChanged(This,eventHandler,token) \
+ ( (This)->lpVtbl -> add_DocumentTitleChanged(This,eventHandler,token) )
+
+#define ICoreWebView2_remove_DocumentTitleChanged(This,token) \
+ ( (This)->lpVtbl -> remove_DocumentTitleChanged(This,token) )
+
+#define ICoreWebView2_get_DocumentTitle(This,title) \
+ ( (This)->lpVtbl -> get_DocumentTitle(This,title) )
+
+#define ICoreWebView2_AddHostObjectToScript(This,name,object) \
+ ( (This)->lpVtbl -> AddHostObjectToScript(This,name,object) )
+
+#define ICoreWebView2_RemoveHostObjectFromScript(This,name) \
+ ( (This)->lpVtbl -> RemoveHostObjectFromScript(This,name) )
+
+#define ICoreWebView2_OpenDevToolsWindow(This) \
+ ( (This)->lpVtbl -> OpenDevToolsWindow(This) )
+
+#define ICoreWebView2_add_ContainsFullScreenElementChanged(This,eventHandler,token) \
+ ( (This)->lpVtbl -> add_ContainsFullScreenElementChanged(This,eventHandler,token) )
+
+#define ICoreWebView2_remove_ContainsFullScreenElementChanged(This,token) \
+ ( (This)->lpVtbl -> remove_ContainsFullScreenElementChanged(This,token) )
+
+#define ICoreWebView2_get_ContainsFullScreenElement(This,containsFullScreenElement) \
+ ( (This)->lpVtbl -> get_ContainsFullScreenElement(This,containsFullScreenElement) )
+
+#define ICoreWebView2_add_WebResourceRequested(This,eventHandler,token) \
+ ( (This)->lpVtbl -> add_WebResourceRequested(This,eventHandler,token) )
+
+#define ICoreWebView2_remove_WebResourceRequested(This,token) \
+ ( (This)->lpVtbl -> remove_WebResourceRequested(This,token) )
+
+#define ICoreWebView2_AddWebResourceRequestedFilter(This,uri,resourceContext) \
+ ( (This)->lpVtbl -> AddWebResourceRequestedFilter(This,uri,resourceContext) )
+
+#define ICoreWebView2_RemoveWebResourceRequestedFilter(This,uri,resourceContext) \
+ ( (This)->lpVtbl -> RemoveWebResourceRequestedFilter(This,uri,resourceContext) )
+
+#define ICoreWebView2_add_WindowCloseRequested(This,eventHandler,token) \
+ ( (This)->lpVtbl -> add_WindowCloseRequested(This,eventHandler,token) )
+
+#define ICoreWebView2_remove_WindowCloseRequested(This,token) \
+ ( (This)->lpVtbl -> remove_WindowCloseRequested(This,token) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __ICoreWebView2_INTERFACE_DEFINED__ */
+
+
+#ifndef __ICoreWebView2_2_INTERFACE_DEFINED__
+#define __ICoreWebView2_2_INTERFACE_DEFINED__
+
+/* interface ICoreWebView2_2 */
+/* [unique][object][uuid] */
+
+
+EXTERN_C __declspec(selectany) const IID IID_ICoreWebView2_2 = {0x9E8F0CF8,0xE670,0x4B5E,{0xB2,0xBC,0x73,0xE0,0x61,0xE3,0x18,0x4C}};
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("9E8F0CF8-E670-4B5E-B2BC-73E061E3184C")
+ ICoreWebView2_2 : public ICoreWebView2
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE add_WebResourceResponseReceived(
+ /* [in] */ ICoreWebView2WebResourceResponseReceivedEventHandler *eventHandler,
+ /* [out] */ EventRegistrationToken *token) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE remove_WebResourceResponseReceived(
+ /* [in] */ EventRegistrationToken token) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE NavigateWithWebResourceRequest(
+ /* [in] */ ICoreWebView2WebResourceRequest *request) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE add_DOMContentLoaded(
+ /* [in] */ ICoreWebView2DOMContentLoadedEventHandler *eventHandler,
+ /* [out] */ EventRegistrationToken *token) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE remove_DOMContentLoaded(
+ /* [in] */ EventRegistrationToken token) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_CookieManager(
+ /* [retval][out] */ ICoreWebView2CookieManager **cookieManager) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_Environment(
+ /* [retval][out] */ ICoreWebView2Environment **environment) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct ICoreWebView2_2Vtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ ICoreWebView2_2 * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ ICoreWebView2_2 * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ ICoreWebView2_2 * This);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_Settings )(
+ ICoreWebView2_2 * This,
+ /* [retval][out] */ ICoreWebView2Settings **settings);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_Source )(
+ ICoreWebView2_2 * This,
+ /* [retval][out] */ LPWSTR *uri);
+
+ HRESULT ( STDMETHODCALLTYPE *Navigate )(
+ ICoreWebView2_2 * This,
+ /* [in] */ LPCWSTR uri);
+
+ HRESULT ( STDMETHODCALLTYPE *NavigateToString )(
+ ICoreWebView2_2 * This,
+ /* [in] */ LPCWSTR htmlContent);
+
+ HRESULT ( STDMETHODCALLTYPE *add_NavigationStarting )(
+ ICoreWebView2_2 * This,
+ /* [in] */ ICoreWebView2NavigationStartingEventHandler *eventHandler,
+ /* [out] */ EventRegistrationToken *token);
+
+ HRESULT ( STDMETHODCALLTYPE *remove_NavigationStarting )(
+ ICoreWebView2_2 * This,
+ /* [in] */ EventRegistrationToken token);
+
+ HRESULT ( STDMETHODCALLTYPE *add_ContentLoading )(
+ ICoreWebView2_2 * This,
+ /* [in] */ ICoreWebView2ContentLoadingEventHandler *eventHandler,
+ /* [out] */ EventRegistrationToken *token);
+
+ HRESULT ( STDMETHODCALLTYPE *remove_ContentLoading )(
+ ICoreWebView2_2 * This,
+ /* [in] */ EventRegistrationToken token);
+
+ HRESULT ( STDMETHODCALLTYPE *add_SourceChanged )(
+ ICoreWebView2_2 * This,
+ /* [in] */ ICoreWebView2SourceChangedEventHandler *eventHandler,
+ /* [out] */ EventRegistrationToken *token);
+
+ HRESULT ( STDMETHODCALLTYPE *remove_SourceChanged )(
+ ICoreWebView2_2 * This,
+ /* [in] */ EventRegistrationToken token);
+
+ HRESULT ( STDMETHODCALLTYPE *add_HistoryChanged )(
+ ICoreWebView2_2 * This,
+ /* [in] */ ICoreWebView2HistoryChangedEventHandler *eventHandler,
+ /* [out] */ EventRegistrationToken *token);
+
+ HRESULT ( STDMETHODCALLTYPE *remove_HistoryChanged )(
+ ICoreWebView2_2 * This,
+ /* [in] */ EventRegistrationToken token);
+
+ HRESULT ( STDMETHODCALLTYPE *add_NavigationCompleted )(
+ ICoreWebView2_2 * This,
+ /* [in] */ ICoreWebView2NavigationCompletedEventHandler *eventHandler,
+ /* [out] */ EventRegistrationToken *token);
+
+ HRESULT ( STDMETHODCALLTYPE *remove_NavigationCompleted )(
+ ICoreWebView2_2 * This,
+ /* [in] */ EventRegistrationToken token);
+
+ HRESULT ( STDMETHODCALLTYPE *add_FrameNavigationStarting )(
+ ICoreWebView2_2 * This,
+ /* [in] */ ICoreWebView2NavigationStartingEventHandler *eventHandler,
+ /* [out] */ EventRegistrationToken *token);
+
+ HRESULT ( STDMETHODCALLTYPE *remove_FrameNavigationStarting )(
+ ICoreWebView2_2 * This,
+ /* [in] */ EventRegistrationToken token);
+
+ HRESULT ( STDMETHODCALLTYPE *add_FrameNavigationCompleted )(
+ ICoreWebView2_2 * This,
+ /* [in] */ ICoreWebView2NavigationCompletedEventHandler *eventHandler,
+ /* [out] */ EventRegistrationToken *token);
+
+ HRESULT ( STDMETHODCALLTYPE *remove_FrameNavigationCompleted )(
+ ICoreWebView2_2 * This,
+ /* [in] */ EventRegistrationToken token);
+
+ HRESULT ( STDMETHODCALLTYPE *add_ScriptDialogOpening )(
+ ICoreWebView2_2 * This,
+ /* [in] */ ICoreWebView2ScriptDialogOpeningEventHandler *eventHandler,
+ /* [out] */ EventRegistrationToken *token);
+
+ HRESULT ( STDMETHODCALLTYPE *remove_ScriptDialogOpening )(
+ ICoreWebView2_2 * This,
+ /* [in] */ EventRegistrationToken token);
+
+ HRESULT ( STDMETHODCALLTYPE *add_PermissionRequested )(
+ ICoreWebView2_2 * This,
+ /* [in] */ ICoreWebView2PermissionRequestedEventHandler *eventHandler,
+ /* [out] */ EventRegistrationToken *token);
+
+ HRESULT ( STDMETHODCALLTYPE *remove_PermissionRequested )(
+ ICoreWebView2_2 * This,
+ /* [in] */ EventRegistrationToken token);
+
+ HRESULT ( STDMETHODCALLTYPE *add_ProcessFailed )(
+ ICoreWebView2_2 * This,
+ /* [in] */ ICoreWebView2ProcessFailedEventHandler *eventHandler,
+ /* [out] */ EventRegistrationToken *token);
+
+ HRESULT ( STDMETHODCALLTYPE *remove_ProcessFailed )(
+ ICoreWebView2_2 * This,
+ /* [in] */ EventRegistrationToken token);
+
+ HRESULT ( STDMETHODCALLTYPE *AddScriptToExecuteOnDocumentCreated )(
+ ICoreWebView2_2 * This,
+ /* [in] */ LPCWSTR javaScript,
+ /* [in] */ ICoreWebView2AddScriptToExecuteOnDocumentCreatedCompletedHandler *handler);
+
+ HRESULT ( STDMETHODCALLTYPE *RemoveScriptToExecuteOnDocumentCreated )(
+ ICoreWebView2_2 * This,
+ /* [in] */ LPCWSTR id);
+
+ HRESULT ( STDMETHODCALLTYPE *ExecuteScript )(
+ ICoreWebView2_2 * This,
+ /* [in] */ LPCWSTR javaScript,
+ /* [in] */ ICoreWebView2ExecuteScriptCompletedHandler *handler);
+
+ HRESULT ( STDMETHODCALLTYPE *CapturePreview )(
+ ICoreWebView2_2 * This,
+ /* [in] */ COREWEBVIEW2_CAPTURE_PREVIEW_IMAGE_FORMAT imageFormat,
+ /* [in] */ IStream *imageStream,
+ /* [in] */ ICoreWebView2CapturePreviewCompletedHandler *handler);
+
+ HRESULT ( STDMETHODCALLTYPE *Reload )(
+ ICoreWebView2_2 * This);
+
+ HRESULT ( STDMETHODCALLTYPE *PostWebMessageAsJson )(
+ ICoreWebView2_2 * This,
+ /* [in] */ LPCWSTR webMessageAsJson);
+
+ HRESULT ( STDMETHODCALLTYPE *PostWebMessageAsString )(
+ ICoreWebView2_2 * This,
+ /* [in] */ LPCWSTR webMessageAsString);
+
+ HRESULT ( STDMETHODCALLTYPE *add_WebMessageReceived )(
+ ICoreWebView2_2 * This,
+ /* [in] */ ICoreWebView2WebMessageReceivedEventHandler *handler,
+ /* [out] */ EventRegistrationToken *token);
+
+ HRESULT ( STDMETHODCALLTYPE *remove_WebMessageReceived )(
+ ICoreWebView2_2 * This,
+ /* [in] */ EventRegistrationToken token);
+
+ HRESULT ( STDMETHODCALLTYPE *CallDevToolsProtocolMethod )(
+ ICoreWebView2_2 * This,
+ /* [in] */ LPCWSTR methodName,
+ /* [in] */ LPCWSTR parametersAsJson,
+ /* [in] */ ICoreWebView2CallDevToolsProtocolMethodCompletedHandler *handler);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_BrowserProcessId )(
+ ICoreWebView2_2 * This,
+ /* [retval][out] */ UINT32 *value);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_CanGoBack )(
+ ICoreWebView2_2 * This,
+ /* [retval][out] */ BOOL *canGoBack);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_CanGoForward )(
+ ICoreWebView2_2 * This,
+ /* [retval][out] */ BOOL *canGoForward);
+
+ HRESULT ( STDMETHODCALLTYPE *GoBack )(
+ ICoreWebView2_2 * This);
+
+ HRESULT ( STDMETHODCALLTYPE *GoForward )(
+ ICoreWebView2_2 * This);
+
+ HRESULT ( STDMETHODCALLTYPE *GetDevToolsProtocolEventReceiver )(
+ ICoreWebView2_2 * This,
+ /* [in] */ LPCWSTR eventName,
+ /* [retval][out] */ ICoreWebView2DevToolsProtocolEventReceiver **receiver);
+
+ HRESULT ( STDMETHODCALLTYPE *Stop )(
+ ICoreWebView2_2 * This);
+
+ HRESULT ( STDMETHODCALLTYPE *add_NewWindowRequested )(
+ ICoreWebView2_2 * This,
+ /* [in] */ ICoreWebView2NewWindowRequestedEventHandler *eventHandler,
+ /* [out] */ EventRegistrationToken *token);
+
+ HRESULT ( STDMETHODCALLTYPE *remove_NewWindowRequested )(
+ ICoreWebView2_2 * This,
+ /* [in] */ EventRegistrationToken token);
+
+ HRESULT ( STDMETHODCALLTYPE *add_DocumentTitleChanged )(
+ ICoreWebView2_2 * This,
+ /* [in] */ ICoreWebView2DocumentTitleChangedEventHandler *eventHandler,
+ /* [out] */ EventRegistrationToken *token);
+
+ HRESULT ( STDMETHODCALLTYPE *remove_DocumentTitleChanged )(
+ ICoreWebView2_2 * This,
+ /* [in] */ EventRegistrationToken token);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_DocumentTitle )(
+ ICoreWebView2_2 * This,
+ /* [retval][out] */ LPWSTR *title);
+
+ HRESULT ( STDMETHODCALLTYPE *AddHostObjectToScript )(
+ ICoreWebView2_2 * This,
+ /* [in] */ LPCWSTR name,
+ /* [in] */ VARIANT *object);
+
+ HRESULT ( STDMETHODCALLTYPE *RemoveHostObjectFromScript )(
+ ICoreWebView2_2 * This,
+ /* [in] */ LPCWSTR name);
+
+ HRESULT ( STDMETHODCALLTYPE *OpenDevToolsWindow )(
+ ICoreWebView2_2 * This);
+
+ HRESULT ( STDMETHODCALLTYPE *add_ContainsFullScreenElementChanged )(
+ ICoreWebView2_2 * This,
+ /* [in] */ ICoreWebView2ContainsFullScreenElementChangedEventHandler *eventHandler,
+ /* [out] */ EventRegistrationToken *token);
+
+ HRESULT ( STDMETHODCALLTYPE *remove_ContainsFullScreenElementChanged )(
+ ICoreWebView2_2 * This,
+ /* [in] */ EventRegistrationToken token);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_ContainsFullScreenElement )(
+ ICoreWebView2_2 * This,
+ /* [retval][out] */ BOOL *containsFullScreenElement);
+
+ HRESULT ( STDMETHODCALLTYPE *add_WebResourceRequested )(
+ ICoreWebView2_2 * This,
+ /* [in] */ ICoreWebView2WebResourceRequestedEventHandler *eventHandler,
+ /* [out] */ EventRegistrationToken *token);
+
+ HRESULT ( STDMETHODCALLTYPE *remove_WebResourceRequested )(
+ ICoreWebView2_2 * This,
+ /* [in] */ EventRegistrationToken token);
+
+ HRESULT ( STDMETHODCALLTYPE *AddWebResourceRequestedFilter )(
+ ICoreWebView2_2 * This,
+ /* [in] */ const LPCWSTR uri,
+ /* [in] */ const COREWEBVIEW2_WEB_RESOURCE_CONTEXT resourceContext);
+
+ HRESULT ( STDMETHODCALLTYPE *RemoveWebResourceRequestedFilter )(
+ ICoreWebView2_2 * This,
+ /* [in] */ const LPCWSTR uri,
+ /* [in] */ const COREWEBVIEW2_WEB_RESOURCE_CONTEXT resourceContext);
+
+ HRESULT ( STDMETHODCALLTYPE *add_WindowCloseRequested )(
+ ICoreWebView2_2 * This,
+ /* [in] */ ICoreWebView2WindowCloseRequestedEventHandler *eventHandler,
+ /* [out] */ EventRegistrationToken *token);
+
+ HRESULT ( STDMETHODCALLTYPE *remove_WindowCloseRequested )(
+ ICoreWebView2_2 * This,
+ /* [in] */ EventRegistrationToken token);
+
+ HRESULT ( STDMETHODCALLTYPE *add_WebResourceResponseReceived )(
+ ICoreWebView2_2 * This,
+ /* [in] */ ICoreWebView2WebResourceResponseReceivedEventHandler *eventHandler,
+ /* [out] */ EventRegistrationToken *token);
+
+ HRESULT ( STDMETHODCALLTYPE *remove_WebResourceResponseReceived )(
+ ICoreWebView2_2 * This,
+ /* [in] */ EventRegistrationToken token);
+
+ HRESULT ( STDMETHODCALLTYPE *NavigateWithWebResourceRequest )(
+ ICoreWebView2_2 * This,
+ /* [in] */ ICoreWebView2WebResourceRequest *request);
+
+ HRESULT ( STDMETHODCALLTYPE *add_DOMContentLoaded )(
+ ICoreWebView2_2 * This,
+ /* [in] */ ICoreWebView2DOMContentLoadedEventHandler *eventHandler,
+ /* [out] */ EventRegistrationToken *token);
+
+ HRESULT ( STDMETHODCALLTYPE *remove_DOMContentLoaded )(
+ ICoreWebView2_2 * This,
+ /* [in] */ EventRegistrationToken token);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_CookieManager )(
+ ICoreWebView2_2 * This,
+ /* [retval][out] */ ICoreWebView2CookieManager **cookieManager);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_Environment )(
+ ICoreWebView2_2 * This,
+ /* [retval][out] */ ICoreWebView2Environment **environment);
+
+ END_INTERFACE
+ } ICoreWebView2_2Vtbl;
+
+ interface ICoreWebView2_2
+ {
+ CONST_VTBL struct ICoreWebView2_2Vtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define ICoreWebView2_2_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define ICoreWebView2_2_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define ICoreWebView2_2_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define ICoreWebView2_2_get_Settings(This,settings) \
+ ( (This)->lpVtbl -> get_Settings(This,settings) )
+
+#define ICoreWebView2_2_get_Source(This,uri) \
+ ( (This)->lpVtbl -> get_Source(This,uri) )
+
+#define ICoreWebView2_2_Navigate(This,uri) \
+ ( (This)->lpVtbl -> Navigate(This,uri) )
+
+#define ICoreWebView2_2_NavigateToString(This,htmlContent) \
+ ( (This)->lpVtbl -> NavigateToString(This,htmlContent) )
+
+#define ICoreWebView2_2_add_NavigationStarting(This,eventHandler,token) \
+ ( (This)->lpVtbl -> add_NavigationStarting(This,eventHandler,token) )
+
+#define ICoreWebView2_2_remove_NavigationStarting(This,token) \
+ ( (This)->lpVtbl -> remove_NavigationStarting(This,token) )
+
+#define ICoreWebView2_2_add_ContentLoading(This,eventHandler,token) \
+ ( (This)->lpVtbl -> add_ContentLoading(This,eventHandler,token) )
+
+#define ICoreWebView2_2_remove_ContentLoading(This,token) \
+ ( (This)->lpVtbl -> remove_ContentLoading(This,token) )
+
+#define ICoreWebView2_2_add_SourceChanged(This,eventHandler,token) \
+ ( (This)->lpVtbl -> add_SourceChanged(This,eventHandler,token) )
+
+#define ICoreWebView2_2_remove_SourceChanged(This,token) \
+ ( (This)->lpVtbl -> remove_SourceChanged(This,token) )
+
+#define ICoreWebView2_2_add_HistoryChanged(This,eventHandler,token) \
+ ( (This)->lpVtbl -> add_HistoryChanged(This,eventHandler,token) )
+
+#define ICoreWebView2_2_remove_HistoryChanged(This,token) \
+ ( (This)->lpVtbl -> remove_HistoryChanged(This,token) )
+
+#define ICoreWebView2_2_add_NavigationCompleted(This,eventHandler,token) \
+ ( (This)->lpVtbl -> add_NavigationCompleted(This,eventHandler,token) )
+
+#define ICoreWebView2_2_remove_NavigationCompleted(This,token) \
+ ( (This)->lpVtbl -> remove_NavigationCompleted(This,token) )
+
+#define ICoreWebView2_2_add_FrameNavigationStarting(This,eventHandler,token) \
+ ( (This)->lpVtbl -> add_FrameNavigationStarting(This,eventHandler,token) )
+
+#define ICoreWebView2_2_remove_FrameNavigationStarting(This,token) \
+ ( (This)->lpVtbl -> remove_FrameNavigationStarting(This,token) )
+
+#define ICoreWebView2_2_add_FrameNavigationCompleted(This,eventHandler,token) \
+ ( (This)->lpVtbl -> add_FrameNavigationCompleted(This,eventHandler,token) )
+
+#define ICoreWebView2_2_remove_FrameNavigationCompleted(This,token) \
+ ( (This)->lpVtbl -> remove_FrameNavigationCompleted(This,token) )
+
+#define ICoreWebView2_2_add_ScriptDialogOpening(This,eventHandler,token) \
+ ( (This)->lpVtbl -> add_ScriptDialogOpening(This,eventHandler,token) )
+
+#define ICoreWebView2_2_remove_ScriptDialogOpening(This,token) \
+ ( (This)->lpVtbl -> remove_ScriptDialogOpening(This,token) )
+
+#define ICoreWebView2_2_add_PermissionRequested(This,eventHandler,token) \
+ ( (This)->lpVtbl -> add_PermissionRequested(This,eventHandler,token) )
+
+#define ICoreWebView2_2_remove_PermissionRequested(This,token) \
+ ( (This)->lpVtbl -> remove_PermissionRequested(This,token) )
+
+#define ICoreWebView2_2_add_ProcessFailed(This,eventHandler,token) \
+ ( (This)->lpVtbl -> add_ProcessFailed(This,eventHandler,token) )
+
+#define ICoreWebView2_2_remove_ProcessFailed(This,token) \
+ ( (This)->lpVtbl -> remove_ProcessFailed(This,token) )
+
+#define ICoreWebView2_2_AddScriptToExecuteOnDocumentCreated(This,javaScript,handler) \
+ ( (This)->lpVtbl -> AddScriptToExecuteOnDocumentCreated(This,javaScript,handler) )
+
+#define ICoreWebView2_2_RemoveScriptToExecuteOnDocumentCreated(This,id) \
+ ( (This)->lpVtbl -> RemoveScriptToExecuteOnDocumentCreated(This,id) )
+
+#define ICoreWebView2_2_ExecuteScript(This,javaScript,handler) \
+ ( (This)->lpVtbl -> ExecuteScript(This,javaScript,handler) )
+
+#define ICoreWebView2_2_CapturePreview(This,imageFormat,imageStream,handler) \
+ ( (This)->lpVtbl -> CapturePreview(This,imageFormat,imageStream,handler) )
+
+#define ICoreWebView2_2_Reload(This) \
+ ( (This)->lpVtbl -> Reload(This) )
+
+#define ICoreWebView2_2_PostWebMessageAsJson(This,webMessageAsJson) \
+ ( (This)->lpVtbl -> PostWebMessageAsJson(This,webMessageAsJson) )
+
+#define ICoreWebView2_2_PostWebMessageAsString(This,webMessageAsString) \
+ ( (This)->lpVtbl -> PostWebMessageAsString(This,webMessageAsString) )
+
+#define ICoreWebView2_2_add_WebMessageReceived(This,handler,token) \
+ ( (This)->lpVtbl -> add_WebMessageReceived(This,handler,token) )
+
+#define ICoreWebView2_2_remove_WebMessageReceived(This,token) \
+ ( (This)->lpVtbl -> remove_WebMessageReceived(This,token) )
+
+#define ICoreWebView2_2_CallDevToolsProtocolMethod(This,methodName,parametersAsJson,handler) \
+ ( (This)->lpVtbl -> CallDevToolsProtocolMethod(This,methodName,parametersAsJson,handler) )
+
+#define ICoreWebView2_2_get_BrowserProcessId(This,value) \
+ ( (This)->lpVtbl -> get_BrowserProcessId(This,value) )
+
+#define ICoreWebView2_2_get_CanGoBack(This,canGoBack) \
+ ( (This)->lpVtbl -> get_CanGoBack(This,canGoBack) )
+
+#define ICoreWebView2_2_get_CanGoForward(This,canGoForward) \
+ ( (This)->lpVtbl -> get_CanGoForward(This,canGoForward) )
+
+#define ICoreWebView2_2_GoBack(This) \
+ ( (This)->lpVtbl -> GoBack(This) )
+
+#define ICoreWebView2_2_GoForward(This) \
+ ( (This)->lpVtbl -> GoForward(This) )
+
+#define ICoreWebView2_2_GetDevToolsProtocolEventReceiver(This,eventName,receiver) \
+ ( (This)->lpVtbl -> GetDevToolsProtocolEventReceiver(This,eventName,receiver) )
+
+#define ICoreWebView2_2_Stop(This) \
+ ( (This)->lpVtbl -> Stop(This) )
+
+#define ICoreWebView2_2_add_NewWindowRequested(This,eventHandler,token) \
+ ( (This)->lpVtbl -> add_NewWindowRequested(This,eventHandler,token) )
+
+#define ICoreWebView2_2_remove_NewWindowRequested(This,token) \
+ ( (This)->lpVtbl -> remove_NewWindowRequested(This,token) )
+
+#define ICoreWebView2_2_add_DocumentTitleChanged(This,eventHandler,token) \
+ ( (This)->lpVtbl -> add_DocumentTitleChanged(This,eventHandler,token) )
+
+#define ICoreWebView2_2_remove_DocumentTitleChanged(This,token) \
+ ( (This)->lpVtbl -> remove_DocumentTitleChanged(This,token) )
+
+#define ICoreWebView2_2_get_DocumentTitle(This,title) \
+ ( (This)->lpVtbl -> get_DocumentTitle(This,title) )
+
+#define ICoreWebView2_2_AddHostObjectToScript(This,name,object) \
+ ( (This)->lpVtbl -> AddHostObjectToScript(This,name,object) )
+
+#define ICoreWebView2_2_RemoveHostObjectFromScript(This,name) \
+ ( (This)->lpVtbl -> RemoveHostObjectFromScript(This,name) )
+
+#define ICoreWebView2_2_OpenDevToolsWindow(This) \
+ ( (This)->lpVtbl -> OpenDevToolsWindow(This) )
+
+#define ICoreWebView2_2_add_ContainsFullScreenElementChanged(This,eventHandler,token) \
+ ( (This)->lpVtbl -> add_ContainsFullScreenElementChanged(This,eventHandler,token) )
+
+#define ICoreWebView2_2_remove_ContainsFullScreenElementChanged(This,token) \
+ ( (This)->lpVtbl -> remove_ContainsFullScreenElementChanged(This,token) )
+
+#define ICoreWebView2_2_get_ContainsFullScreenElement(This,containsFullScreenElement) \
+ ( (This)->lpVtbl -> get_ContainsFullScreenElement(This,containsFullScreenElement) )
+
+#define ICoreWebView2_2_add_WebResourceRequested(This,eventHandler,token) \
+ ( (This)->lpVtbl -> add_WebResourceRequested(This,eventHandler,token) )
+
+#define ICoreWebView2_2_remove_WebResourceRequested(This,token) \
+ ( (This)->lpVtbl -> remove_WebResourceRequested(This,token) )
+
+#define ICoreWebView2_2_AddWebResourceRequestedFilter(This,uri,resourceContext) \
+ ( (This)->lpVtbl -> AddWebResourceRequestedFilter(This,uri,resourceContext) )
+
+#define ICoreWebView2_2_RemoveWebResourceRequestedFilter(This,uri,resourceContext) \
+ ( (This)->lpVtbl -> RemoveWebResourceRequestedFilter(This,uri,resourceContext) )
+
+#define ICoreWebView2_2_add_WindowCloseRequested(This,eventHandler,token) \
+ ( (This)->lpVtbl -> add_WindowCloseRequested(This,eventHandler,token) )
+
+#define ICoreWebView2_2_remove_WindowCloseRequested(This,token) \
+ ( (This)->lpVtbl -> remove_WindowCloseRequested(This,token) )
+
+
+#define ICoreWebView2_2_add_WebResourceResponseReceived(This,eventHandler,token) \
+ ( (This)->lpVtbl -> add_WebResourceResponseReceived(This,eventHandler,token) )
+
+#define ICoreWebView2_2_remove_WebResourceResponseReceived(This,token) \
+ ( (This)->lpVtbl -> remove_WebResourceResponseReceived(This,token) )
+
+#define ICoreWebView2_2_NavigateWithWebResourceRequest(This,request) \
+ ( (This)->lpVtbl -> NavigateWithWebResourceRequest(This,request) )
+
+#define ICoreWebView2_2_add_DOMContentLoaded(This,eventHandler,token) \
+ ( (This)->lpVtbl -> add_DOMContentLoaded(This,eventHandler,token) )
+
+#define ICoreWebView2_2_remove_DOMContentLoaded(This,token) \
+ ( (This)->lpVtbl -> remove_DOMContentLoaded(This,token) )
+
+#define ICoreWebView2_2_get_CookieManager(This,cookieManager) \
+ ( (This)->lpVtbl -> get_CookieManager(This,cookieManager) )
+
+#define ICoreWebView2_2_get_Environment(This,environment) \
+ ( (This)->lpVtbl -> get_Environment(This,environment) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __ICoreWebView2_2_INTERFACE_DEFINED__ */
+
+
+#ifndef __ICoreWebView2_3_INTERFACE_DEFINED__
+#define __ICoreWebView2_3_INTERFACE_DEFINED__
+
+/* interface ICoreWebView2_3 */
+/* [unique][object][uuid] */
+
+
+EXTERN_C __declspec(selectany) const IID IID_ICoreWebView2_3 = {0xA0D6DF20,0x3B92,0x416D,{0xAA,0x0C,0x43,0x7A,0x9C,0x72,0x78,0x57}};
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("A0D6DF20-3B92-416D-AA0C-437A9C727857")
+ ICoreWebView2_3 : public ICoreWebView2_2
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE TrySuspend(
+ /* [in] */ ICoreWebView2TrySuspendCompletedHandler *handler) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE Resume( void) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_IsSuspended(
+ /* [retval][out] */ BOOL *isSuspended) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SetVirtualHostNameToFolderMapping(
+ /* [in] */ LPCWSTR hostName,
+ /* [in] */ LPCWSTR folderPath,
+ /* [in] */ COREWEBVIEW2_HOST_RESOURCE_ACCESS_KIND accessKind) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE ClearVirtualHostNameToFolderMapping(
+ /* [in] */ LPCWSTR hostName) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct ICoreWebView2_3Vtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ ICoreWebView2_3 * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ ICoreWebView2_3 * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ ICoreWebView2_3 * This);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_Settings )(
+ ICoreWebView2_3 * This,
+ /* [retval][out] */ ICoreWebView2Settings **settings);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_Source )(
+ ICoreWebView2_3 * This,
+ /* [retval][out] */ LPWSTR *uri);
+
+ HRESULT ( STDMETHODCALLTYPE *Navigate )(
+ ICoreWebView2_3 * This,
+ /* [in] */ LPCWSTR uri);
+
+ HRESULT ( STDMETHODCALLTYPE *NavigateToString )(
+ ICoreWebView2_3 * This,
+ /* [in] */ LPCWSTR htmlContent);
+
+ HRESULT ( STDMETHODCALLTYPE *add_NavigationStarting )(
+ ICoreWebView2_3 * This,
+ /* [in] */ ICoreWebView2NavigationStartingEventHandler *eventHandler,
+ /* [out] */ EventRegistrationToken *token);
+
+ HRESULT ( STDMETHODCALLTYPE *remove_NavigationStarting )(
+ ICoreWebView2_3 * This,
+ /* [in] */ EventRegistrationToken token);
+
+ HRESULT ( STDMETHODCALLTYPE *add_ContentLoading )(
+ ICoreWebView2_3 * This,
+ /* [in] */ ICoreWebView2ContentLoadingEventHandler *eventHandler,
+ /* [out] */ EventRegistrationToken *token);
+
+ HRESULT ( STDMETHODCALLTYPE *remove_ContentLoading )(
+ ICoreWebView2_3 * This,
+ /* [in] */ EventRegistrationToken token);
+
+ HRESULT ( STDMETHODCALLTYPE *add_SourceChanged )(
+ ICoreWebView2_3 * This,
+ /* [in] */ ICoreWebView2SourceChangedEventHandler *eventHandler,
+ /* [out] */ EventRegistrationToken *token);
+
+ HRESULT ( STDMETHODCALLTYPE *remove_SourceChanged )(
+ ICoreWebView2_3 * This,
+ /* [in] */ EventRegistrationToken token);
+
+ HRESULT ( STDMETHODCALLTYPE *add_HistoryChanged )(
+ ICoreWebView2_3 * This,
+ /* [in] */ ICoreWebView2HistoryChangedEventHandler *eventHandler,
+ /* [out] */ EventRegistrationToken *token);
+
+ HRESULT ( STDMETHODCALLTYPE *remove_HistoryChanged )(
+ ICoreWebView2_3 * This,
+ /* [in] */ EventRegistrationToken token);
+
+ HRESULT ( STDMETHODCALLTYPE *add_NavigationCompleted )(
+ ICoreWebView2_3 * This,
+ /* [in] */ ICoreWebView2NavigationCompletedEventHandler *eventHandler,
+ /* [out] */ EventRegistrationToken *token);
+
+ HRESULT ( STDMETHODCALLTYPE *remove_NavigationCompleted )(
+ ICoreWebView2_3 * This,
+ /* [in] */ EventRegistrationToken token);
+
+ HRESULT ( STDMETHODCALLTYPE *add_FrameNavigationStarting )(
+ ICoreWebView2_3 * This,
+ /* [in] */ ICoreWebView2NavigationStartingEventHandler *eventHandler,
+ /* [out] */ EventRegistrationToken *token);
+
+ HRESULT ( STDMETHODCALLTYPE *remove_FrameNavigationStarting )(
+ ICoreWebView2_3 * This,
+ /* [in] */ EventRegistrationToken token);
+
+ HRESULT ( STDMETHODCALLTYPE *add_FrameNavigationCompleted )(
+ ICoreWebView2_3 * This,
+ /* [in] */ ICoreWebView2NavigationCompletedEventHandler *eventHandler,
+ /* [out] */ EventRegistrationToken *token);
+
+ HRESULT ( STDMETHODCALLTYPE *remove_FrameNavigationCompleted )(
+ ICoreWebView2_3 * This,
+ /* [in] */ EventRegistrationToken token);
+
+ HRESULT ( STDMETHODCALLTYPE *add_ScriptDialogOpening )(
+ ICoreWebView2_3 * This,
+ /* [in] */ ICoreWebView2ScriptDialogOpeningEventHandler *eventHandler,
+ /* [out] */ EventRegistrationToken *token);
+
+ HRESULT ( STDMETHODCALLTYPE *remove_ScriptDialogOpening )(
+ ICoreWebView2_3 * This,
+ /* [in] */ EventRegistrationToken token);
+
+ HRESULT ( STDMETHODCALLTYPE *add_PermissionRequested )(
+ ICoreWebView2_3 * This,
+ /* [in] */ ICoreWebView2PermissionRequestedEventHandler *eventHandler,
+ /* [out] */ EventRegistrationToken *token);
+
+ HRESULT ( STDMETHODCALLTYPE *remove_PermissionRequested )(
+ ICoreWebView2_3 * This,
+ /* [in] */ EventRegistrationToken token);
+
+ HRESULT ( STDMETHODCALLTYPE *add_ProcessFailed )(
+ ICoreWebView2_3 * This,
+ /* [in] */ ICoreWebView2ProcessFailedEventHandler *eventHandler,
+ /* [out] */ EventRegistrationToken *token);
+
+ HRESULT ( STDMETHODCALLTYPE *remove_ProcessFailed )(
+ ICoreWebView2_3 * This,
+ /* [in] */ EventRegistrationToken token);
+
+ HRESULT ( STDMETHODCALLTYPE *AddScriptToExecuteOnDocumentCreated )(
+ ICoreWebView2_3 * This,
+ /* [in] */ LPCWSTR javaScript,
+ /* [in] */ ICoreWebView2AddScriptToExecuteOnDocumentCreatedCompletedHandler *handler);
+
+ HRESULT ( STDMETHODCALLTYPE *RemoveScriptToExecuteOnDocumentCreated )(
+ ICoreWebView2_3 * This,
+ /* [in] */ LPCWSTR id);
+
+ HRESULT ( STDMETHODCALLTYPE *ExecuteScript )(
+ ICoreWebView2_3 * This,
+ /* [in] */ LPCWSTR javaScript,
+ /* [in] */ ICoreWebView2ExecuteScriptCompletedHandler *handler);
+
+ HRESULT ( STDMETHODCALLTYPE *CapturePreview )(
+ ICoreWebView2_3 * This,
+ /* [in] */ COREWEBVIEW2_CAPTURE_PREVIEW_IMAGE_FORMAT imageFormat,
+ /* [in] */ IStream *imageStream,
+ /* [in] */ ICoreWebView2CapturePreviewCompletedHandler *handler);
+
+ HRESULT ( STDMETHODCALLTYPE *Reload )(
+ ICoreWebView2_3 * This);
+
+ HRESULT ( STDMETHODCALLTYPE *PostWebMessageAsJson )(
+ ICoreWebView2_3 * This,
+ /* [in] */ LPCWSTR webMessageAsJson);
+
+ HRESULT ( STDMETHODCALLTYPE *PostWebMessageAsString )(
+ ICoreWebView2_3 * This,
+ /* [in] */ LPCWSTR webMessageAsString);
+
+ HRESULT ( STDMETHODCALLTYPE *add_WebMessageReceived )(
+ ICoreWebView2_3 * This,
+ /* [in] */ ICoreWebView2WebMessageReceivedEventHandler *handler,
+ /* [out] */ EventRegistrationToken *token);
+
+ HRESULT ( STDMETHODCALLTYPE *remove_WebMessageReceived )(
+ ICoreWebView2_3 * This,
+ /* [in] */ EventRegistrationToken token);
+
+ HRESULT ( STDMETHODCALLTYPE *CallDevToolsProtocolMethod )(
+ ICoreWebView2_3 * This,
+ /* [in] */ LPCWSTR methodName,
+ /* [in] */ LPCWSTR parametersAsJson,
+ /* [in] */ ICoreWebView2CallDevToolsProtocolMethodCompletedHandler *handler);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_BrowserProcessId )(
+ ICoreWebView2_3 * This,
+ /* [retval][out] */ UINT32 *value);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_CanGoBack )(
+ ICoreWebView2_3 * This,
+ /* [retval][out] */ BOOL *canGoBack);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_CanGoForward )(
+ ICoreWebView2_3 * This,
+ /* [retval][out] */ BOOL *canGoForward);
+
+ HRESULT ( STDMETHODCALLTYPE *GoBack )(
+ ICoreWebView2_3 * This);
+
+ HRESULT ( STDMETHODCALLTYPE *GoForward )(
+ ICoreWebView2_3 * This);
+
+ HRESULT ( STDMETHODCALLTYPE *GetDevToolsProtocolEventReceiver )(
+ ICoreWebView2_3 * This,
+ /* [in] */ LPCWSTR eventName,
+ /* [retval][out] */ ICoreWebView2DevToolsProtocolEventReceiver **receiver);
+
+ HRESULT ( STDMETHODCALLTYPE *Stop )(
+ ICoreWebView2_3 * This);
+
+ HRESULT ( STDMETHODCALLTYPE *add_NewWindowRequested )(
+ ICoreWebView2_3 * This,
+ /* [in] */ ICoreWebView2NewWindowRequestedEventHandler *eventHandler,
+ /* [out] */ EventRegistrationToken *token);
+
+ HRESULT ( STDMETHODCALLTYPE *remove_NewWindowRequested )(
+ ICoreWebView2_3 * This,
+ /* [in] */ EventRegistrationToken token);
+
+ HRESULT ( STDMETHODCALLTYPE *add_DocumentTitleChanged )(
+ ICoreWebView2_3 * This,
+ /* [in] */ ICoreWebView2DocumentTitleChangedEventHandler *eventHandler,
+ /* [out] */ EventRegistrationToken *token);
+
+ HRESULT ( STDMETHODCALLTYPE *remove_DocumentTitleChanged )(
+ ICoreWebView2_3 * This,
+ /* [in] */ EventRegistrationToken token);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_DocumentTitle )(
+ ICoreWebView2_3 * This,
+ /* [retval][out] */ LPWSTR *title);
+
+ HRESULT ( STDMETHODCALLTYPE *AddHostObjectToScript )(
+ ICoreWebView2_3 * This,
+ /* [in] */ LPCWSTR name,
+ /* [in] */ VARIANT *object);
+
+ HRESULT ( STDMETHODCALLTYPE *RemoveHostObjectFromScript )(
+ ICoreWebView2_3 * This,
+ /* [in] */ LPCWSTR name);
+
+ HRESULT ( STDMETHODCALLTYPE *OpenDevToolsWindow )(
+ ICoreWebView2_3 * This);
+
+ HRESULT ( STDMETHODCALLTYPE *add_ContainsFullScreenElementChanged )(
+ ICoreWebView2_3 * This,
+ /* [in] */ ICoreWebView2ContainsFullScreenElementChangedEventHandler *eventHandler,
+ /* [out] */ EventRegistrationToken *token);
+
+ HRESULT ( STDMETHODCALLTYPE *remove_ContainsFullScreenElementChanged )(
+ ICoreWebView2_3 * This,
+ /* [in] */ EventRegistrationToken token);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_ContainsFullScreenElement )(
+ ICoreWebView2_3 * This,
+ /* [retval][out] */ BOOL *containsFullScreenElement);
+
+ HRESULT ( STDMETHODCALLTYPE *add_WebResourceRequested )(
+ ICoreWebView2_3 * This,
+ /* [in] */ ICoreWebView2WebResourceRequestedEventHandler *eventHandler,
+ /* [out] */ EventRegistrationToken *token);
+
+ HRESULT ( STDMETHODCALLTYPE *remove_WebResourceRequested )(
+ ICoreWebView2_3 * This,
+ /* [in] */ EventRegistrationToken token);
+
+ HRESULT ( STDMETHODCALLTYPE *AddWebResourceRequestedFilter )(
+ ICoreWebView2_3 * This,
+ /* [in] */ const LPCWSTR uri,
+ /* [in] */ const COREWEBVIEW2_WEB_RESOURCE_CONTEXT resourceContext);
+
+ HRESULT ( STDMETHODCALLTYPE *RemoveWebResourceRequestedFilter )(
+ ICoreWebView2_3 * This,
+ /* [in] */ const LPCWSTR uri,
+ /* [in] */ const COREWEBVIEW2_WEB_RESOURCE_CONTEXT resourceContext);
+
+ HRESULT ( STDMETHODCALLTYPE *add_WindowCloseRequested )(
+ ICoreWebView2_3 * This,
+ /* [in] */ ICoreWebView2WindowCloseRequestedEventHandler *eventHandler,
+ /* [out] */ EventRegistrationToken *token);
+
+ HRESULT ( STDMETHODCALLTYPE *remove_WindowCloseRequested )(
+ ICoreWebView2_3 * This,
+ /* [in] */ EventRegistrationToken token);
+
+ HRESULT ( STDMETHODCALLTYPE *add_WebResourceResponseReceived )(
+ ICoreWebView2_3 * This,
+ /* [in] */ ICoreWebView2WebResourceResponseReceivedEventHandler *eventHandler,
+ /* [out] */ EventRegistrationToken *token);
+
+ HRESULT ( STDMETHODCALLTYPE *remove_WebResourceResponseReceived )(
+ ICoreWebView2_3 * This,
+ /* [in] */ EventRegistrationToken token);
+
+ HRESULT ( STDMETHODCALLTYPE *NavigateWithWebResourceRequest )(
+ ICoreWebView2_3 * This,
+ /* [in] */ ICoreWebView2WebResourceRequest *request);
+
+ HRESULT ( STDMETHODCALLTYPE *add_DOMContentLoaded )(
+ ICoreWebView2_3 * This,
+ /* [in] */ ICoreWebView2DOMContentLoadedEventHandler *eventHandler,
+ /* [out] */ EventRegistrationToken *token);
+
+ HRESULT ( STDMETHODCALLTYPE *remove_DOMContentLoaded )(
+ ICoreWebView2_3 * This,
+ /* [in] */ EventRegistrationToken token);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_CookieManager )(
+ ICoreWebView2_3 * This,
+ /* [retval][out] */ ICoreWebView2CookieManager **cookieManager);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_Environment )(
+ ICoreWebView2_3 * This,
+ /* [retval][out] */ ICoreWebView2Environment **environment);
+
+ HRESULT ( STDMETHODCALLTYPE *TrySuspend )(
+ ICoreWebView2_3 * This,
+ /* [in] */ ICoreWebView2TrySuspendCompletedHandler *handler);
+
+ HRESULT ( STDMETHODCALLTYPE *Resume )(
+ ICoreWebView2_3 * This);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_IsSuspended )(
+ ICoreWebView2_3 * This,
+ /* [retval][out] */ BOOL *isSuspended);
+
+ HRESULT ( STDMETHODCALLTYPE *SetVirtualHostNameToFolderMapping )(
+ ICoreWebView2_3 * This,
+ /* [in] */ LPCWSTR hostName,
+ /* [in] */ LPCWSTR folderPath,
+ /* [in] */ COREWEBVIEW2_HOST_RESOURCE_ACCESS_KIND accessKind);
+
+ HRESULT ( STDMETHODCALLTYPE *ClearVirtualHostNameToFolderMapping )(
+ ICoreWebView2_3 * This,
+ /* [in] */ LPCWSTR hostName);
+
+ END_INTERFACE
+ } ICoreWebView2_3Vtbl;
+
+ interface ICoreWebView2_3
+ {
+ CONST_VTBL struct ICoreWebView2_3Vtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define ICoreWebView2_3_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define ICoreWebView2_3_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define ICoreWebView2_3_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define ICoreWebView2_3_get_Settings(This,settings) \
+ ( (This)->lpVtbl -> get_Settings(This,settings) )
+
+#define ICoreWebView2_3_get_Source(This,uri) \
+ ( (This)->lpVtbl -> get_Source(This,uri) )
+
+#define ICoreWebView2_3_Navigate(This,uri) \
+ ( (This)->lpVtbl -> Navigate(This,uri) )
+
+#define ICoreWebView2_3_NavigateToString(This,htmlContent) \
+ ( (This)->lpVtbl -> NavigateToString(This,htmlContent) )
+
+#define ICoreWebView2_3_add_NavigationStarting(This,eventHandler,token) \
+ ( (This)->lpVtbl -> add_NavigationStarting(This,eventHandler,token) )
+
+#define ICoreWebView2_3_remove_NavigationStarting(This,token) \
+ ( (This)->lpVtbl -> remove_NavigationStarting(This,token) )
+
+#define ICoreWebView2_3_add_ContentLoading(This,eventHandler,token) \
+ ( (This)->lpVtbl -> add_ContentLoading(This,eventHandler,token) )
+
+#define ICoreWebView2_3_remove_ContentLoading(This,token) \
+ ( (This)->lpVtbl -> remove_ContentLoading(This,token) )
+
+#define ICoreWebView2_3_add_SourceChanged(This,eventHandler,token) \
+ ( (This)->lpVtbl -> add_SourceChanged(This,eventHandler,token) )
+
+#define ICoreWebView2_3_remove_SourceChanged(This,token) \
+ ( (This)->lpVtbl -> remove_SourceChanged(This,token) )
+
+#define ICoreWebView2_3_add_HistoryChanged(This,eventHandler,token) \
+ ( (This)->lpVtbl -> add_HistoryChanged(This,eventHandler,token) )
+
+#define ICoreWebView2_3_remove_HistoryChanged(This,token) \
+ ( (This)->lpVtbl -> remove_HistoryChanged(This,token) )
+
+#define ICoreWebView2_3_add_NavigationCompleted(This,eventHandler,token) \
+ ( (This)->lpVtbl -> add_NavigationCompleted(This,eventHandler,token) )
+
+#define ICoreWebView2_3_remove_NavigationCompleted(This,token) \
+ ( (This)->lpVtbl -> remove_NavigationCompleted(This,token) )
+
+#define ICoreWebView2_3_add_FrameNavigationStarting(This,eventHandler,token) \
+ ( (This)->lpVtbl -> add_FrameNavigationStarting(This,eventHandler,token) )
+
+#define ICoreWebView2_3_remove_FrameNavigationStarting(This,token) \
+ ( (This)->lpVtbl -> remove_FrameNavigationStarting(This,token) )
+
+#define ICoreWebView2_3_add_FrameNavigationCompleted(This,eventHandler,token) \
+ ( (This)->lpVtbl -> add_FrameNavigationCompleted(This,eventHandler,token) )
+
+#define ICoreWebView2_3_remove_FrameNavigationCompleted(This,token) \
+ ( (This)->lpVtbl -> remove_FrameNavigationCompleted(This,token) )
+
+#define ICoreWebView2_3_add_ScriptDialogOpening(This,eventHandler,token) \
+ ( (This)->lpVtbl -> add_ScriptDialogOpening(This,eventHandler,token) )
+
+#define ICoreWebView2_3_remove_ScriptDialogOpening(This,token) \
+ ( (This)->lpVtbl -> remove_ScriptDialogOpening(This,token) )
+
+#define ICoreWebView2_3_add_PermissionRequested(This,eventHandler,token) \
+ ( (This)->lpVtbl -> add_PermissionRequested(This,eventHandler,token) )
+
+#define ICoreWebView2_3_remove_PermissionRequested(This,token) \
+ ( (This)->lpVtbl -> remove_PermissionRequested(This,token) )
+
+#define ICoreWebView2_3_add_ProcessFailed(This,eventHandler,token) \
+ ( (This)->lpVtbl -> add_ProcessFailed(This,eventHandler,token) )
+
+#define ICoreWebView2_3_remove_ProcessFailed(This,token) \
+ ( (This)->lpVtbl -> remove_ProcessFailed(This,token) )
+
+#define ICoreWebView2_3_AddScriptToExecuteOnDocumentCreated(This,javaScript,handler) \
+ ( (This)->lpVtbl -> AddScriptToExecuteOnDocumentCreated(This,javaScript,handler) )
+
+#define ICoreWebView2_3_RemoveScriptToExecuteOnDocumentCreated(This,id) \
+ ( (This)->lpVtbl -> RemoveScriptToExecuteOnDocumentCreated(This,id) )
+
+#define ICoreWebView2_3_ExecuteScript(This,javaScript,handler) \
+ ( (This)->lpVtbl -> ExecuteScript(This,javaScript,handler) )
+
+#define ICoreWebView2_3_CapturePreview(This,imageFormat,imageStream,handler) \
+ ( (This)->lpVtbl -> CapturePreview(This,imageFormat,imageStream,handler) )
+
+#define ICoreWebView2_3_Reload(This) \
+ ( (This)->lpVtbl -> Reload(This) )
+
+#define ICoreWebView2_3_PostWebMessageAsJson(This,webMessageAsJson) \
+ ( (This)->lpVtbl -> PostWebMessageAsJson(This,webMessageAsJson) )
+
+#define ICoreWebView2_3_PostWebMessageAsString(This,webMessageAsString) \
+ ( (This)->lpVtbl -> PostWebMessageAsString(This,webMessageAsString) )
+
+#define ICoreWebView2_3_add_WebMessageReceived(This,handler,token) \
+ ( (This)->lpVtbl -> add_WebMessageReceived(This,handler,token) )
+
+#define ICoreWebView2_3_remove_WebMessageReceived(This,token) \
+ ( (This)->lpVtbl -> remove_WebMessageReceived(This,token) )
+
+#define ICoreWebView2_3_CallDevToolsProtocolMethod(This,methodName,parametersAsJson,handler) \
+ ( (This)->lpVtbl -> CallDevToolsProtocolMethod(This,methodName,parametersAsJson,handler) )
+
+#define ICoreWebView2_3_get_BrowserProcessId(This,value) \
+ ( (This)->lpVtbl -> get_BrowserProcessId(This,value) )
+
+#define ICoreWebView2_3_get_CanGoBack(This,canGoBack) \
+ ( (This)->lpVtbl -> get_CanGoBack(This,canGoBack) )
+
+#define ICoreWebView2_3_get_CanGoForward(This,canGoForward) \
+ ( (This)->lpVtbl -> get_CanGoForward(This,canGoForward) )
+
+#define ICoreWebView2_3_GoBack(This) \
+ ( (This)->lpVtbl -> GoBack(This) )
+
+#define ICoreWebView2_3_GoForward(This) \
+ ( (This)->lpVtbl -> GoForward(This) )
+
+#define ICoreWebView2_3_GetDevToolsProtocolEventReceiver(This,eventName,receiver) \
+ ( (This)->lpVtbl -> GetDevToolsProtocolEventReceiver(This,eventName,receiver) )
+
+#define ICoreWebView2_3_Stop(This) \
+ ( (This)->lpVtbl -> Stop(This) )
+
+#define ICoreWebView2_3_add_NewWindowRequested(This,eventHandler,token) \
+ ( (This)->lpVtbl -> add_NewWindowRequested(This,eventHandler,token) )
+
+#define ICoreWebView2_3_remove_NewWindowRequested(This,token) \
+ ( (This)->lpVtbl -> remove_NewWindowRequested(This,token) )
+
+#define ICoreWebView2_3_add_DocumentTitleChanged(This,eventHandler,token) \
+ ( (This)->lpVtbl -> add_DocumentTitleChanged(This,eventHandler,token) )
+
+#define ICoreWebView2_3_remove_DocumentTitleChanged(This,token) \
+ ( (This)->lpVtbl -> remove_DocumentTitleChanged(This,token) )
+
+#define ICoreWebView2_3_get_DocumentTitle(This,title) \
+ ( (This)->lpVtbl -> get_DocumentTitle(This,title) )
+
+#define ICoreWebView2_3_AddHostObjectToScript(This,name,object) \
+ ( (This)->lpVtbl -> AddHostObjectToScript(This,name,object) )
+
+#define ICoreWebView2_3_RemoveHostObjectFromScript(This,name) \
+ ( (This)->lpVtbl -> RemoveHostObjectFromScript(This,name) )
+
+#define ICoreWebView2_3_OpenDevToolsWindow(This) \
+ ( (This)->lpVtbl -> OpenDevToolsWindow(This) )
+
+#define ICoreWebView2_3_add_ContainsFullScreenElementChanged(This,eventHandler,token) \
+ ( (This)->lpVtbl -> add_ContainsFullScreenElementChanged(This,eventHandler,token) )
+
+#define ICoreWebView2_3_remove_ContainsFullScreenElementChanged(This,token) \
+ ( (This)->lpVtbl -> remove_ContainsFullScreenElementChanged(This,token) )
+
+#define ICoreWebView2_3_get_ContainsFullScreenElement(This,containsFullScreenElement) \
+ ( (This)->lpVtbl -> get_ContainsFullScreenElement(This,containsFullScreenElement) )
+
+#define ICoreWebView2_3_add_WebResourceRequested(This,eventHandler,token) \
+ ( (This)->lpVtbl -> add_WebResourceRequested(This,eventHandler,token) )
+
+#define ICoreWebView2_3_remove_WebResourceRequested(This,token) \
+ ( (This)->lpVtbl -> remove_WebResourceRequested(This,token) )
+
+#define ICoreWebView2_3_AddWebResourceRequestedFilter(This,uri,resourceContext) \
+ ( (This)->lpVtbl -> AddWebResourceRequestedFilter(This,uri,resourceContext) )
+
+#define ICoreWebView2_3_RemoveWebResourceRequestedFilter(This,uri,resourceContext) \
+ ( (This)->lpVtbl -> RemoveWebResourceRequestedFilter(This,uri,resourceContext) )
+
+#define ICoreWebView2_3_add_WindowCloseRequested(This,eventHandler,token) \
+ ( (This)->lpVtbl -> add_WindowCloseRequested(This,eventHandler,token) )
+
+#define ICoreWebView2_3_remove_WindowCloseRequested(This,token) \
+ ( (This)->lpVtbl -> remove_WindowCloseRequested(This,token) )
+
+
+#define ICoreWebView2_3_add_WebResourceResponseReceived(This,eventHandler,token) \
+ ( (This)->lpVtbl -> add_WebResourceResponseReceived(This,eventHandler,token) )
+
+#define ICoreWebView2_3_remove_WebResourceResponseReceived(This,token) \
+ ( (This)->lpVtbl -> remove_WebResourceResponseReceived(This,token) )
+
+#define ICoreWebView2_3_NavigateWithWebResourceRequest(This,request) \
+ ( (This)->lpVtbl -> NavigateWithWebResourceRequest(This,request) )
+
+#define ICoreWebView2_3_add_DOMContentLoaded(This,eventHandler,token) \
+ ( (This)->lpVtbl -> add_DOMContentLoaded(This,eventHandler,token) )
+
+#define ICoreWebView2_3_remove_DOMContentLoaded(This,token) \
+ ( (This)->lpVtbl -> remove_DOMContentLoaded(This,token) )
+
+#define ICoreWebView2_3_get_CookieManager(This,cookieManager) \
+ ( (This)->lpVtbl -> get_CookieManager(This,cookieManager) )
+
+#define ICoreWebView2_3_get_Environment(This,environment) \
+ ( (This)->lpVtbl -> get_Environment(This,environment) )
+
+
+#define ICoreWebView2_3_TrySuspend(This,handler) \
+ ( (This)->lpVtbl -> TrySuspend(This,handler) )
+
+#define ICoreWebView2_3_Resume(This) \
+ ( (This)->lpVtbl -> Resume(This) )
+
+#define ICoreWebView2_3_get_IsSuspended(This,isSuspended) \
+ ( (This)->lpVtbl -> get_IsSuspended(This,isSuspended) )
+
+#define ICoreWebView2_3_SetVirtualHostNameToFolderMapping(This,hostName,folderPath,accessKind) \
+ ( (This)->lpVtbl -> SetVirtualHostNameToFolderMapping(This,hostName,folderPath,accessKind) )
+
+#define ICoreWebView2_3_ClearVirtualHostNameToFolderMapping(This,hostName) \
+ ( (This)->lpVtbl -> ClearVirtualHostNameToFolderMapping(This,hostName) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __ICoreWebView2_3_INTERFACE_DEFINED__ */
+
+
+#ifndef __ICoreWebView2CompositionController_INTERFACE_DEFINED__
+#define __ICoreWebView2CompositionController_INTERFACE_DEFINED__
+
+/* interface ICoreWebView2CompositionController */
+/* [unique][object][uuid] */
+
+
+EXTERN_C __declspec(selectany) const IID IID_ICoreWebView2CompositionController = {0x3df9b733,0xb9ae,0x4a15,{0x86,0xb4,0xeb,0x9e,0xe9,0x82,0x64,0x69}};
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("3df9b733-b9ae-4a15-86b4-eb9ee9826469")
+ ICoreWebView2CompositionController : public IUnknown
+ {
+ public:
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_RootVisualTarget(
+ /* [retval][out] */ IUnknown **target) = 0;
+
+ virtual /* [propput] */ HRESULT STDMETHODCALLTYPE put_RootVisualTarget(
+ /* [in] */ IUnknown *target) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SendMouseInput(
+ /* [in] */ COREWEBVIEW2_MOUSE_EVENT_KIND eventKind,
+ /* [in] */ COREWEBVIEW2_MOUSE_EVENT_VIRTUAL_KEYS virtualKeys,
+ /* [in] */ UINT32 mouseData,
+ /* [in] */ POINT point) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SendPointerInput(
+ /* [in] */ COREWEBVIEW2_POINTER_EVENT_KIND eventKind,
+ /* [in] */ ICoreWebView2PointerInfo *pointerInfo) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_Cursor(
+ /* [retval][out] */ HCURSOR *cursor) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_SystemCursorId(
+ /* [retval][out] */ UINT32 *systemCursorId) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE add_CursorChanged(
+ /* [in] */ ICoreWebView2CursorChangedEventHandler *eventHandler,
+ /* [out] */ EventRegistrationToken *token) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE remove_CursorChanged(
+ /* [in] */ EventRegistrationToken token) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct ICoreWebView2CompositionControllerVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ ICoreWebView2CompositionController * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ ICoreWebView2CompositionController * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ ICoreWebView2CompositionController * This);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_RootVisualTarget )(
+ ICoreWebView2CompositionController * This,
+ /* [retval][out] */ IUnknown **target);
+
+ /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_RootVisualTarget )(
+ ICoreWebView2CompositionController * This,
+ /* [in] */ IUnknown *target);
+
+ HRESULT ( STDMETHODCALLTYPE *SendMouseInput )(
+ ICoreWebView2CompositionController * This,
+ /* [in] */ COREWEBVIEW2_MOUSE_EVENT_KIND eventKind,
+ /* [in] */ COREWEBVIEW2_MOUSE_EVENT_VIRTUAL_KEYS virtualKeys,
+ /* [in] */ UINT32 mouseData,
+ /* [in] */ POINT point);
+
+ HRESULT ( STDMETHODCALLTYPE *SendPointerInput )(
+ ICoreWebView2CompositionController * This,
+ /* [in] */ COREWEBVIEW2_POINTER_EVENT_KIND eventKind,
+ /* [in] */ ICoreWebView2PointerInfo *pointerInfo);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_Cursor )(
+ ICoreWebView2CompositionController * This,
+ /* [retval][out] */ HCURSOR *cursor);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_SystemCursorId )(
+ ICoreWebView2CompositionController * This,
+ /* [retval][out] */ UINT32 *systemCursorId);
+
+ HRESULT ( STDMETHODCALLTYPE *add_CursorChanged )(
+ ICoreWebView2CompositionController * This,
+ /* [in] */ ICoreWebView2CursorChangedEventHandler *eventHandler,
+ /* [out] */ EventRegistrationToken *token);
+
+ HRESULT ( STDMETHODCALLTYPE *remove_CursorChanged )(
+ ICoreWebView2CompositionController * This,
+ /* [in] */ EventRegistrationToken token);
+
+ END_INTERFACE
+ } ICoreWebView2CompositionControllerVtbl;
+
+ interface ICoreWebView2CompositionController
+ {
+ CONST_VTBL struct ICoreWebView2CompositionControllerVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define ICoreWebView2CompositionController_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define ICoreWebView2CompositionController_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define ICoreWebView2CompositionController_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define ICoreWebView2CompositionController_get_RootVisualTarget(This,target) \
+ ( (This)->lpVtbl -> get_RootVisualTarget(This,target) )
+
+#define ICoreWebView2CompositionController_put_RootVisualTarget(This,target) \
+ ( (This)->lpVtbl -> put_RootVisualTarget(This,target) )
+
+#define ICoreWebView2CompositionController_SendMouseInput(This,eventKind,virtualKeys,mouseData,point) \
+ ( (This)->lpVtbl -> SendMouseInput(This,eventKind,virtualKeys,mouseData,point) )
+
+#define ICoreWebView2CompositionController_SendPointerInput(This,eventKind,pointerInfo) \
+ ( (This)->lpVtbl -> SendPointerInput(This,eventKind,pointerInfo) )
+
+#define ICoreWebView2CompositionController_get_Cursor(This,cursor) \
+ ( (This)->lpVtbl -> get_Cursor(This,cursor) )
+
+#define ICoreWebView2CompositionController_get_SystemCursorId(This,systemCursorId) \
+ ( (This)->lpVtbl -> get_SystemCursorId(This,systemCursorId) )
+
+#define ICoreWebView2CompositionController_add_CursorChanged(This,eventHandler,token) \
+ ( (This)->lpVtbl -> add_CursorChanged(This,eventHandler,token) )
+
+#define ICoreWebView2CompositionController_remove_CursorChanged(This,token) \
+ ( (This)->lpVtbl -> remove_CursorChanged(This,token) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __ICoreWebView2CompositionController_INTERFACE_DEFINED__ */
+
+
+#ifndef __ICoreWebView2CompositionController2_INTERFACE_DEFINED__
+#define __ICoreWebView2CompositionController2_INTERFACE_DEFINED__
+
+/* interface ICoreWebView2CompositionController2 */
+/* [unique][object][uuid] */
+
+
+EXTERN_C __declspec(selectany) const IID IID_ICoreWebView2CompositionController2 = {0x0b6a3d24,0x49cb,0x4806,{0xba,0x20,0xb5,0xe0,0x73,0x4a,0x7b,0x26}};
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("0b6a3d24-49cb-4806-ba20-b5e0734a7b26")
+ ICoreWebView2CompositionController2 : public ICoreWebView2CompositionController
+ {
+ public:
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_UIAProvider(
+ /* [retval][out] */ IUnknown **provider) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct ICoreWebView2CompositionController2Vtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ ICoreWebView2CompositionController2 * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ ICoreWebView2CompositionController2 * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ ICoreWebView2CompositionController2 * This);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_RootVisualTarget )(
+ ICoreWebView2CompositionController2 * This,
+ /* [retval][out] */ IUnknown **target);
+
+ /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_RootVisualTarget )(
+ ICoreWebView2CompositionController2 * This,
+ /* [in] */ IUnknown *target);
+
+ HRESULT ( STDMETHODCALLTYPE *SendMouseInput )(
+ ICoreWebView2CompositionController2 * This,
+ /* [in] */ COREWEBVIEW2_MOUSE_EVENT_KIND eventKind,
+ /* [in] */ COREWEBVIEW2_MOUSE_EVENT_VIRTUAL_KEYS virtualKeys,
+ /* [in] */ UINT32 mouseData,
+ /* [in] */ POINT point);
+
+ HRESULT ( STDMETHODCALLTYPE *SendPointerInput )(
+ ICoreWebView2CompositionController2 * This,
+ /* [in] */ COREWEBVIEW2_POINTER_EVENT_KIND eventKind,
+ /* [in] */ ICoreWebView2PointerInfo *pointerInfo);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_Cursor )(
+ ICoreWebView2CompositionController2 * This,
+ /* [retval][out] */ HCURSOR *cursor);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_SystemCursorId )(
+ ICoreWebView2CompositionController2 * This,
+ /* [retval][out] */ UINT32 *systemCursorId);
+
+ HRESULT ( STDMETHODCALLTYPE *add_CursorChanged )(
+ ICoreWebView2CompositionController2 * This,
+ /* [in] */ ICoreWebView2CursorChangedEventHandler *eventHandler,
+ /* [out] */ EventRegistrationToken *token);
+
+ HRESULT ( STDMETHODCALLTYPE *remove_CursorChanged )(
+ ICoreWebView2CompositionController2 * This,
+ /* [in] */ EventRegistrationToken token);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_UIAProvider )(
+ ICoreWebView2CompositionController2 * This,
+ /* [retval][out] */ IUnknown **provider);
+
+ END_INTERFACE
+ } ICoreWebView2CompositionController2Vtbl;
+
+ interface ICoreWebView2CompositionController2
+ {
+ CONST_VTBL struct ICoreWebView2CompositionController2Vtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define ICoreWebView2CompositionController2_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define ICoreWebView2CompositionController2_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define ICoreWebView2CompositionController2_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define ICoreWebView2CompositionController2_get_RootVisualTarget(This,target) \
+ ( (This)->lpVtbl -> get_RootVisualTarget(This,target) )
+
+#define ICoreWebView2CompositionController2_put_RootVisualTarget(This,target) \
+ ( (This)->lpVtbl -> put_RootVisualTarget(This,target) )
+
+#define ICoreWebView2CompositionController2_SendMouseInput(This,eventKind,virtualKeys,mouseData,point) \
+ ( (This)->lpVtbl -> SendMouseInput(This,eventKind,virtualKeys,mouseData,point) )
+
+#define ICoreWebView2CompositionController2_SendPointerInput(This,eventKind,pointerInfo) \
+ ( (This)->lpVtbl -> SendPointerInput(This,eventKind,pointerInfo) )
+
+#define ICoreWebView2CompositionController2_get_Cursor(This,cursor) \
+ ( (This)->lpVtbl -> get_Cursor(This,cursor) )
+
+#define ICoreWebView2CompositionController2_get_SystemCursorId(This,systemCursorId) \
+ ( (This)->lpVtbl -> get_SystemCursorId(This,systemCursorId) )
+
+#define ICoreWebView2CompositionController2_add_CursorChanged(This,eventHandler,token) \
+ ( (This)->lpVtbl -> add_CursorChanged(This,eventHandler,token) )
+
+#define ICoreWebView2CompositionController2_remove_CursorChanged(This,token) \
+ ( (This)->lpVtbl -> remove_CursorChanged(This,token) )
+
+
+#define ICoreWebView2CompositionController2_get_UIAProvider(This,provider) \
+ ( (This)->lpVtbl -> get_UIAProvider(This,provider) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __ICoreWebView2CompositionController2_INTERFACE_DEFINED__ */
+
+
+#ifndef __ICoreWebView2Controller_INTERFACE_DEFINED__
+#define __ICoreWebView2Controller_INTERFACE_DEFINED__
+
+/* interface ICoreWebView2Controller */
+/* [unique][object][uuid] */
+
+
+EXTERN_C __declspec(selectany) const IID IID_ICoreWebView2Controller = {0x4d00c0d1,0x9434,0x4eb6,{0x80,0x78,0x86,0x97,0xa5,0x60,0x33,0x4f}};
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("4d00c0d1-9434-4eb6-8078-8697a560334f")
+ ICoreWebView2Controller : public IUnknown
+ {
+ public:
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_IsVisible(
+ /* [retval][out] */ BOOL *isVisible) = 0;
+
+ virtual /* [propput] */ HRESULT STDMETHODCALLTYPE put_IsVisible(
+ /* [in] */ BOOL isVisible) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_Bounds(
+ /* [retval][out] */ RECT *bounds) = 0;
+
+ virtual /* [propput] */ HRESULT STDMETHODCALLTYPE put_Bounds(
+ /* [in] */ RECT bounds) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_ZoomFactor(
+ /* [retval][out] */ double *zoomFactor) = 0;
+
+ virtual /* [propput] */ HRESULT STDMETHODCALLTYPE put_ZoomFactor(
+ /* [in] */ double zoomFactor) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE add_ZoomFactorChanged(
+ /* [in] */ ICoreWebView2ZoomFactorChangedEventHandler *eventHandler,
+ /* [out] */ EventRegistrationToken *token) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE remove_ZoomFactorChanged(
+ /* [in] */ EventRegistrationToken token) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SetBoundsAndZoomFactor(
+ /* [in] */ RECT bounds,
+ /* [in] */ double zoomFactor) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE MoveFocus(
+ /* [in] */ COREWEBVIEW2_MOVE_FOCUS_REASON reason) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE add_MoveFocusRequested(
+ /* [in] */ ICoreWebView2MoveFocusRequestedEventHandler *eventHandler,
+ /* [out] */ EventRegistrationToken *token) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE remove_MoveFocusRequested(
+ /* [in] */ EventRegistrationToken token) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE add_GotFocus(
+ /* [in] */ ICoreWebView2FocusChangedEventHandler *eventHandler,
+ /* [out] */ EventRegistrationToken *token) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE remove_GotFocus(
+ /* [in] */ EventRegistrationToken token) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE add_LostFocus(
+ /* [in] */ ICoreWebView2FocusChangedEventHandler *eventHandler,
+ /* [out] */ EventRegistrationToken *token) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE remove_LostFocus(
+ /* [in] */ EventRegistrationToken token) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE add_AcceleratorKeyPressed(
+ /* [in] */ ICoreWebView2AcceleratorKeyPressedEventHandler *eventHandler,
+ /* [out] */ EventRegistrationToken *token) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE remove_AcceleratorKeyPressed(
+ /* [in] */ EventRegistrationToken token) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_ParentWindow(
+ /* [retval][out] */ HWND *parentWindow) = 0;
+
+ virtual /* [propput] */ HRESULT STDMETHODCALLTYPE put_ParentWindow(
+ /* [in] */ HWND parentWindow) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE NotifyParentWindowPositionChanged( void) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE Close( void) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_CoreWebView2(
+ /* [retval][out] */ ICoreWebView2 **coreWebView2) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct ICoreWebView2ControllerVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ ICoreWebView2Controller * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ ICoreWebView2Controller * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ ICoreWebView2Controller * This);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_IsVisible )(
+ ICoreWebView2Controller * This,
+ /* [retval][out] */ BOOL *isVisible);
+
+ /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_IsVisible )(
+ ICoreWebView2Controller * This,
+ /* [in] */ BOOL isVisible);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_Bounds )(
+ ICoreWebView2Controller * This,
+ /* [retval][out] */ RECT *bounds);
+
+ /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_Bounds )(
+ ICoreWebView2Controller * This,
+ /* [in] */ RECT bounds);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_ZoomFactor )(
+ ICoreWebView2Controller * This,
+ /* [retval][out] */ double *zoomFactor);
+
+ /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_ZoomFactor )(
+ ICoreWebView2Controller * This,
+ /* [in] */ double zoomFactor);
+
+ HRESULT ( STDMETHODCALLTYPE *add_ZoomFactorChanged )(
+ ICoreWebView2Controller * This,
+ /* [in] */ ICoreWebView2ZoomFactorChangedEventHandler *eventHandler,
+ /* [out] */ EventRegistrationToken *token);
+
+ HRESULT ( STDMETHODCALLTYPE *remove_ZoomFactorChanged )(
+ ICoreWebView2Controller * This,
+ /* [in] */ EventRegistrationToken token);
+
+ HRESULT ( STDMETHODCALLTYPE *SetBoundsAndZoomFactor )(
+ ICoreWebView2Controller * This,
+ /* [in] */ RECT bounds,
+ /* [in] */ double zoomFactor);
+
+ HRESULT ( STDMETHODCALLTYPE *MoveFocus )(
+ ICoreWebView2Controller * This,
+ /* [in] */ COREWEBVIEW2_MOVE_FOCUS_REASON reason);
+
+ HRESULT ( STDMETHODCALLTYPE *add_MoveFocusRequested )(
+ ICoreWebView2Controller * This,
+ /* [in] */ ICoreWebView2MoveFocusRequestedEventHandler *eventHandler,
+ /* [out] */ EventRegistrationToken *token);
+
+ HRESULT ( STDMETHODCALLTYPE *remove_MoveFocusRequested )(
+ ICoreWebView2Controller * This,
+ /* [in] */ EventRegistrationToken token);
+
+ HRESULT ( STDMETHODCALLTYPE *add_GotFocus )(
+ ICoreWebView2Controller * This,
+ /* [in] */ ICoreWebView2FocusChangedEventHandler *eventHandler,
+ /* [out] */ EventRegistrationToken *token);
+
+ HRESULT ( STDMETHODCALLTYPE *remove_GotFocus )(
+ ICoreWebView2Controller * This,
+ /* [in] */ EventRegistrationToken token);
+
+ HRESULT ( STDMETHODCALLTYPE *add_LostFocus )(
+ ICoreWebView2Controller * This,
+ /* [in] */ ICoreWebView2FocusChangedEventHandler *eventHandler,
+ /* [out] */ EventRegistrationToken *token);
+
+ HRESULT ( STDMETHODCALLTYPE *remove_LostFocus )(
+ ICoreWebView2Controller * This,
+ /* [in] */ EventRegistrationToken token);
+
+ HRESULT ( STDMETHODCALLTYPE *add_AcceleratorKeyPressed )(
+ ICoreWebView2Controller * This,
+ /* [in] */ ICoreWebView2AcceleratorKeyPressedEventHandler *eventHandler,
+ /* [out] */ EventRegistrationToken *token);
+
+ HRESULT ( STDMETHODCALLTYPE *remove_AcceleratorKeyPressed )(
+ ICoreWebView2Controller * This,
+ /* [in] */ EventRegistrationToken token);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_ParentWindow )(
+ ICoreWebView2Controller * This,
+ /* [retval][out] */ HWND *parentWindow);
+
+ /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_ParentWindow )(
+ ICoreWebView2Controller * This,
+ /* [in] */ HWND parentWindow);
+
+ HRESULT ( STDMETHODCALLTYPE *NotifyParentWindowPositionChanged )(
+ ICoreWebView2Controller * This);
+
+ HRESULT ( STDMETHODCALLTYPE *Close )(
+ ICoreWebView2Controller * This);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_CoreWebView2 )(
+ ICoreWebView2Controller * This,
+ /* [retval][out] */ ICoreWebView2 **coreWebView2);
+
+ END_INTERFACE
+ } ICoreWebView2ControllerVtbl;
+
+ interface ICoreWebView2Controller
+ {
+ CONST_VTBL struct ICoreWebView2ControllerVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define ICoreWebView2Controller_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define ICoreWebView2Controller_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define ICoreWebView2Controller_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define ICoreWebView2Controller_get_IsVisible(This,isVisible) \
+ ( (This)->lpVtbl -> get_IsVisible(This,isVisible) )
+
+#define ICoreWebView2Controller_put_IsVisible(This,isVisible) \
+ ( (This)->lpVtbl -> put_IsVisible(This,isVisible) )
+
+#define ICoreWebView2Controller_get_Bounds(This,bounds) \
+ ( (This)->lpVtbl -> get_Bounds(This,bounds) )
+
+#define ICoreWebView2Controller_put_Bounds(This,bounds) \
+ ( (This)->lpVtbl -> put_Bounds(This,bounds) )
+
+#define ICoreWebView2Controller_get_ZoomFactor(This,zoomFactor) \
+ ( (This)->lpVtbl -> get_ZoomFactor(This,zoomFactor) )
+
+#define ICoreWebView2Controller_put_ZoomFactor(This,zoomFactor) \
+ ( (This)->lpVtbl -> put_ZoomFactor(This,zoomFactor) )
+
+#define ICoreWebView2Controller_add_ZoomFactorChanged(This,eventHandler,token) \
+ ( (This)->lpVtbl -> add_ZoomFactorChanged(This,eventHandler,token) )
+
+#define ICoreWebView2Controller_remove_ZoomFactorChanged(This,token) \
+ ( (This)->lpVtbl -> remove_ZoomFactorChanged(This,token) )
+
+#define ICoreWebView2Controller_SetBoundsAndZoomFactor(This,bounds,zoomFactor) \
+ ( (This)->lpVtbl -> SetBoundsAndZoomFactor(This,bounds,zoomFactor) )
+
+#define ICoreWebView2Controller_MoveFocus(This,reason) \
+ ( (This)->lpVtbl -> MoveFocus(This,reason) )
+
+#define ICoreWebView2Controller_add_MoveFocusRequested(This,eventHandler,token) \
+ ( (This)->lpVtbl -> add_MoveFocusRequested(This,eventHandler,token) )
+
+#define ICoreWebView2Controller_remove_MoveFocusRequested(This,token) \
+ ( (This)->lpVtbl -> remove_MoveFocusRequested(This,token) )
+
+#define ICoreWebView2Controller_add_GotFocus(This,eventHandler,token) \
+ ( (This)->lpVtbl -> add_GotFocus(This,eventHandler,token) )
+
+#define ICoreWebView2Controller_remove_GotFocus(This,token) \
+ ( (This)->lpVtbl -> remove_GotFocus(This,token) )
+
+#define ICoreWebView2Controller_add_LostFocus(This,eventHandler,token) \
+ ( (This)->lpVtbl -> add_LostFocus(This,eventHandler,token) )
+
+#define ICoreWebView2Controller_remove_LostFocus(This,token) \
+ ( (This)->lpVtbl -> remove_LostFocus(This,token) )
+
+#define ICoreWebView2Controller_add_AcceleratorKeyPressed(This,eventHandler,token) \
+ ( (This)->lpVtbl -> add_AcceleratorKeyPressed(This,eventHandler,token) )
+
+#define ICoreWebView2Controller_remove_AcceleratorKeyPressed(This,token) \
+ ( (This)->lpVtbl -> remove_AcceleratorKeyPressed(This,token) )
+
+#define ICoreWebView2Controller_get_ParentWindow(This,parentWindow) \
+ ( (This)->lpVtbl -> get_ParentWindow(This,parentWindow) )
+
+#define ICoreWebView2Controller_put_ParentWindow(This,parentWindow) \
+ ( (This)->lpVtbl -> put_ParentWindow(This,parentWindow) )
+
+#define ICoreWebView2Controller_NotifyParentWindowPositionChanged(This) \
+ ( (This)->lpVtbl -> NotifyParentWindowPositionChanged(This) )
+
+#define ICoreWebView2Controller_Close(This) \
+ ( (This)->lpVtbl -> Close(This) )
+
+#define ICoreWebView2Controller_get_CoreWebView2(This,coreWebView2) \
+ ( (This)->lpVtbl -> get_CoreWebView2(This,coreWebView2) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __ICoreWebView2Controller_INTERFACE_DEFINED__ */
+
+
+#ifndef __ICoreWebView2Controller2_INTERFACE_DEFINED__
+#define __ICoreWebView2Controller2_INTERFACE_DEFINED__
+
+/* interface ICoreWebView2Controller2 */
+/* [unique][object][uuid] */
+
+
+EXTERN_C __declspec(selectany) const IID IID_ICoreWebView2Controller2 = {0xc979903e,0xd4ca,0x4228,{0x92,0xeb,0x47,0xee,0x3f,0xa9,0x6e,0xab}};
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("c979903e-d4ca-4228-92eb-47ee3fa96eab")
+ ICoreWebView2Controller2 : public ICoreWebView2Controller
+ {
+ public:
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_DefaultBackgroundColor(
+ /* [retval][out] */ COREWEBVIEW2_COLOR *backgroundColor) = 0;
+
+ virtual /* [propput] */ HRESULT STDMETHODCALLTYPE put_DefaultBackgroundColor(
+ /* [in] */ COREWEBVIEW2_COLOR backgroundColor) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct ICoreWebView2Controller2Vtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ ICoreWebView2Controller2 * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ ICoreWebView2Controller2 * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ ICoreWebView2Controller2 * This);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_IsVisible )(
+ ICoreWebView2Controller2 * This,
+ /* [retval][out] */ BOOL *isVisible);
+
+ /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_IsVisible )(
+ ICoreWebView2Controller2 * This,
+ /* [in] */ BOOL isVisible);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_Bounds )(
+ ICoreWebView2Controller2 * This,
+ /* [retval][out] */ RECT *bounds);
+
+ /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_Bounds )(
+ ICoreWebView2Controller2 * This,
+ /* [in] */ RECT bounds);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_ZoomFactor )(
+ ICoreWebView2Controller2 * This,
+ /* [retval][out] */ double *zoomFactor);
+
+ /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_ZoomFactor )(
+ ICoreWebView2Controller2 * This,
+ /* [in] */ double zoomFactor);
+
+ HRESULT ( STDMETHODCALLTYPE *add_ZoomFactorChanged )(
+ ICoreWebView2Controller2 * This,
+ /* [in] */ ICoreWebView2ZoomFactorChangedEventHandler *eventHandler,
+ /* [out] */ EventRegistrationToken *token);
+
+ HRESULT ( STDMETHODCALLTYPE *remove_ZoomFactorChanged )(
+ ICoreWebView2Controller2 * This,
+ /* [in] */ EventRegistrationToken token);
+
+ HRESULT ( STDMETHODCALLTYPE *SetBoundsAndZoomFactor )(
+ ICoreWebView2Controller2 * This,
+ /* [in] */ RECT bounds,
+ /* [in] */ double zoomFactor);
+
+ HRESULT ( STDMETHODCALLTYPE *MoveFocus )(
+ ICoreWebView2Controller2 * This,
+ /* [in] */ COREWEBVIEW2_MOVE_FOCUS_REASON reason);
+
+ HRESULT ( STDMETHODCALLTYPE *add_MoveFocusRequested )(
+ ICoreWebView2Controller2 * This,
+ /* [in] */ ICoreWebView2MoveFocusRequestedEventHandler *eventHandler,
+ /* [out] */ EventRegistrationToken *token);
+
+ HRESULT ( STDMETHODCALLTYPE *remove_MoveFocusRequested )(
+ ICoreWebView2Controller2 * This,
+ /* [in] */ EventRegistrationToken token);
+
+ HRESULT ( STDMETHODCALLTYPE *add_GotFocus )(
+ ICoreWebView2Controller2 * This,
+ /* [in] */ ICoreWebView2FocusChangedEventHandler *eventHandler,
+ /* [out] */ EventRegistrationToken *token);
+
+ HRESULT ( STDMETHODCALLTYPE *remove_GotFocus )(
+ ICoreWebView2Controller2 * This,
+ /* [in] */ EventRegistrationToken token);
+
+ HRESULT ( STDMETHODCALLTYPE *add_LostFocus )(
+ ICoreWebView2Controller2 * This,
+ /* [in] */ ICoreWebView2FocusChangedEventHandler *eventHandler,
+ /* [out] */ EventRegistrationToken *token);
+
+ HRESULT ( STDMETHODCALLTYPE *remove_LostFocus )(
+ ICoreWebView2Controller2 * This,
+ /* [in] */ EventRegistrationToken token);
+
+ HRESULT ( STDMETHODCALLTYPE *add_AcceleratorKeyPressed )(
+ ICoreWebView2Controller2 * This,
+ /* [in] */ ICoreWebView2AcceleratorKeyPressedEventHandler *eventHandler,
+ /* [out] */ EventRegistrationToken *token);
+
+ HRESULT ( STDMETHODCALLTYPE *remove_AcceleratorKeyPressed )(
+ ICoreWebView2Controller2 * This,
+ /* [in] */ EventRegistrationToken token);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_ParentWindow )(
+ ICoreWebView2Controller2 * This,
+ /* [retval][out] */ HWND *parentWindow);
+
+ /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_ParentWindow )(
+ ICoreWebView2Controller2 * This,
+ /* [in] */ HWND parentWindow);
+
+ HRESULT ( STDMETHODCALLTYPE *NotifyParentWindowPositionChanged )(
+ ICoreWebView2Controller2 * This);
+
+ HRESULT ( STDMETHODCALLTYPE *Close )(
+ ICoreWebView2Controller2 * This);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_CoreWebView2 )(
+ ICoreWebView2Controller2 * This,
+ /* [retval][out] */ ICoreWebView2 **coreWebView2);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_DefaultBackgroundColor )(
+ ICoreWebView2Controller2 * This,
+ /* [retval][out] */ COREWEBVIEW2_COLOR *backgroundColor);
+
+ /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_DefaultBackgroundColor )(
+ ICoreWebView2Controller2 * This,
+ /* [in] */ COREWEBVIEW2_COLOR backgroundColor);
+
+ END_INTERFACE
+ } ICoreWebView2Controller2Vtbl;
+
+ interface ICoreWebView2Controller2
+ {
+ CONST_VTBL struct ICoreWebView2Controller2Vtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define ICoreWebView2Controller2_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define ICoreWebView2Controller2_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define ICoreWebView2Controller2_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define ICoreWebView2Controller2_get_IsVisible(This,isVisible) \
+ ( (This)->lpVtbl -> get_IsVisible(This,isVisible) )
+
+#define ICoreWebView2Controller2_put_IsVisible(This,isVisible) \
+ ( (This)->lpVtbl -> put_IsVisible(This,isVisible) )
+
+#define ICoreWebView2Controller2_get_Bounds(This,bounds) \
+ ( (This)->lpVtbl -> get_Bounds(This,bounds) )
+
+#define ICoreWebView2Controller2_put_Bounds(This,bounds) \
+ ( (This)->lpVtbl -> put_Bounds(This,bounds) )
+
+#define ICoreWebView2Controller2_get_ZoomFactor(This,zoomFactor) \
+ ( (This)->lpVtbl -> get_ZoomFactor(This,zoomFactor) )
+
+#define ICoreWebView2Controller2_put_ZoomFactor(This,zoomFactor) \
+ ( (This)->lpVtbl -> put_ZoomFactor(This,zoomFactor) )
+
+#define ICoreWebView2Controller2_add_ZoomFactorChanged(This,eventHandler,token) \
+ ( (This)->lpVtbl -> add_ZoomFactorChanged(This,eventHandler,token) )
+
+#define ICoreWebView2Controller2_remove_ZoomFactorChanged(This,token) \
+ ( (This)->lpVtbl -> remove_ZoomFactorChanged(This,token) )
+
+#define ICoreWebView2Controller2_SetBoundsAndZoomFactor(This,bounds,zoomFactor) \
+ ( (This)->lpVtbl -> SetBoundsAndZoomFactor(This,bounds,zoomFactor) )
+
+#define ICoreWebView2Controller2_MoveFocus(This,reason) \
+ ( (This)->lpVtbl -> MoveFocus(This,reason) )
+
+#define ICoreWebView2Controller2_add_MoveFocusRequested(This,eventHandler,token) \
+ ( (This)->lpVtbl -> add_MoveFocusRequested(This,eventHandler,token) )
+
+#define ICoreWebView2Controller2_remove_MoveFocusRequested(This,token) \
+ ( (This)->lpVtbl -> remove_MoveFocusRequested(This,token) )
+
+#define ICoreWebView2Controller2_add_GotFocus(This,eventHandler,token) \
+ ( (This)->lpVtbl -> add_GotFocus(This,eventHandler,token) )
+
+#define ICoreWebView2Controller2_remove_GotFocus(This,token) \
+ ( (This)->lpVtbl -> remove_GotFocus(This,token) )
+
+#define ICoreWebView2Controller2_add_LostFocus(This,eventHandler,token) \
+ ( (This)->lpVtbl -> add_LostFocus(This,eventHandler,token) )
+
+#define ICoreWebView2Controller2_remove_LostFocus(This,token) \
+ ( (This)->lpVtbl -> remove_LostFocus(This,token) )
+
+#define ICoreWebView2Controller2_add_AcceleratorKeyPressed(This,eventHandler,token) \
+ ( (This)->lpVtbl -> add_AcceleratorKeyPressed(This,eventHandler,token) )
+
+#define ICoreWebView2Controller2_remove_AcceleratorKeyPressed(This,token) \
+ ( (This)->lpVtbl -> remove_AcceleratorKeyPressed(This,token) )
+
+#define ICoreWebView2Controller2_get_ParentWindow(This,parentWindow) \
+ ( (This)->lpVtbl -> get_ParentWindow(This,parentWindow) )
+
+#define ICoreWebView2Controller2_put_ParentWindow(This,parentWindow) \
+ ( (This)->lpVtbl -> put_ParentWindow(This,parentWindow) )
+
+#define ICoreWebView2Controller2_NotifyParentWindowPositionChanged(This) \
+ ( (This)->lpVtbl -> NotifyParentWindowPositionChanged(This) )
+
+#define ICoreWebView2Controller2_Close(This) \
+ ( (This)->lpVtbl -> Close(This) )
+
+#define ICoreWebView2Controller2_get_CoreWebView2(This,coreWebView2) \
+ ( (This)->lpVtbl -> get_CoreWebView2(This,coreWebView2) )
+
+
+#define ICoreWebView2Controller2_get_DefaultBackgroundColor(This,backgroundColor) \
+ ( (This)->lpVtbl -> get_DefaultBackgroundColor(This,backgroundColor) )
+
+#define ICoreWebView2Controller2_put_DefaultBackgroundColor(This,backgroundColor) \
+ ( (This)->lpVtbl -> put_DefaultBackgroundColor(This,backgroundColor) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __ICoreWebView2Controller2_INTERFACE_DEFINED__ */
+
+
+#ifndef __ICoreWebView2Controller3_INTERFACE_DEFINED__
+#define __ICoreWebView2Controller3_INTERFACE_DEFINED__
+
+/* interface ICoreWebView2Controller3 */
+/* [unique][object][uuid] */
+
+
+EXTERN_C __declspec(selectany) const IID IID_ICoreWebView2Controller3 = {0xf9614724,0x5d2b,0x41dc,{0xae,0xf7,0x73,0xd6,0x2b,0x51,0x54,0x3b}};
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("f9614724-5d2b-41dc-aef7-73d62b51543b")
+ ICoreWebView2Controller3 : public ICoreWebView2Controller2
+ {
+ public:
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_RasterizationScale(
+ /* [retval][out] */ double *scale) = 0;
+
+ virtual /* [propput] */ HRESULT STDMETHODCALLTYPE put_RasterizationScale(
+ /* [in] */ double scale) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_ShouldDetectMonitorScaleChanges(
+ /* [retval][out] */ BOOL *value) = 0;
+
+ virtual /* [propput] */ HRESULT STDMETHODCALLTYPE put_ShouldDetectMonitorScaleChanges(
+ /* [in] */ BOOL value) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE add_RasterizationScaleChanged(
+ /* [in] */ ICoreWebView2RasterizationScaleChangedEventHandler *eventHandler,
+ /* [out] */ EventRegistrationToken *token) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE remove_RasterizationScaleChanged(
+ /* [in] */ EventRegistrationToken token) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_BoundsMode(
+ /* [retval][out] */ COREWEBVIEW2_BOUNDS_MODE *boundsMode) = 0;
+
+ virtual /* [propput] */ HRESULT STDMETHODCALLTYPE put_BoundsMode(
+ /* [in] */ COREWEBVIEW2_BOUNDS_MODE boundsMode) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct ICoreWebView2Controller3Vtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ ICoreWebView2Controller3 * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ ICoreWebView2Controller3 * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ ICoreWebView2Controller3 * This);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_IsVisible )(
+ ICoreWebView2Controller3 * This,
+ /* [retval][out] */ BOOL *isVisible);
+
+ /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_IsVisible )(
+ ICoreWebView2Controller3 * This,
+ /* [in] */ BOOL isVisible);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_Bounds )(
+ ICoreWebView2Controller3 * This,
+ /* [retval][out] */ RECT *bounds);
+
+ /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_Bounds )(
+ ICoreWebView2Controller3 * This,
+ /* [in] */ RECT bounds);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_ZoomFactor )(
+ ICoreWebView2Controller3 * This,
+ /* [retval][out] */ double *zoomFactor);
+
+ /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_ZoomFactor )(
+ ICoreWebView2Controller3 * This,
+ /* [in] */ double zoomFactor);
+
+ HRESULT ( STDMETHODCALLTYPE *add_ZoomFactorChanged )(
+ ICoreWebView2Controller3 * This,
+ /* [in] */ ICoreWebView2ZoomFactorChangedEventHandler *eventHandler,
+ /* [out] */ EventRegistrationToken *token);
+
+ HRESULT ( STDMETHODCALLTYPE *remove_ZoomFactorChanged )(
+ ICoreWebView2Controller3 * This,
+ /* [in] */ EventRegistrationToken token);
+
+ HRESULT ( STDMETHODCALLTYPE *SetBoundsAndZoomFactor )(
+ ICoreWebView2Controller3 * This,
+ /* [in] */ RECT bounds,
+ /* [in] */ double zoomFactor);
+
+ HRESULT ( STDMETHODCALLTYPE *MoveFocus )(
+ ICoreWebView2Controller3 * This,
+ /* [in] */ COREWEBVIEW2_MOVE_FOCUS_REASON reason);
+
+ HRESULT ( STDMETHODCALLTYPE *add_MoveFocusRequested )(
+ ICoreWebView2Controller3 * This,
+ /* [in] */ ICoreWebView2MoveFocusRequestedEventHandler *eventHandler,
+ /* [out] */ EventRegistrationToken *token);
+
+ HRESULT ( STDMETHODCALLTYPE *remove_MoveFocusRequested )(
+ ICoreWebView2Controller3 * This,
+ /* [in] */ EventRegistrationToken token);
+
+ HRESULT ( STDMETHODCALLTYPE *add_GotFocus )(
+ ICoreWebView2Controller3 * This,
+ /* [in] */ ICoreWebView2FocusChangedEventHandler *eventHandler,
+ /* [out] */ EventRegistrationToken *token);
+
+ HRESULT ( STDMETHODCALLTYPE *remove_GotFocus )(
+ ICoreWebView2Controller3 * This,
+ /* [in] */ EventRegistrationToken token);
+
+ HRESULT ( STDMETHODCALLTYPE *add_LostFocus )(
+ ICoreWebView2Controller3 * This,
+ /* [in] */ ICoreWebView2FocusChangedEventHandler *eventHandler,
+ /* [out] */ EventRegistrationToken *token);
+
+ HRESULT ( STDMETHODCALLTYPE *remove_LostFocus )(
+ ICoreWebView2Controller3 * This,
+ /* [in] */ EventRegistrationToken token);
+
+ HRESULT ( STDMETHODCALLTYPE *add_AcceleratorKeyPressed )(
+ ICoreWebView2Controller3 * This,
+ /* [in] */ ICoreWebView2AcceleratorKeyPressedEventHandler *eventHandler,
+ /* [out] */ EventRegistrationToken *token);
+
+ HRESULT ( STDMETHODCALLTYPE *remove_AcceleratorKeyPressed )(
+ ICoreWebView2Controller3 * This,
+ /* [in] */ EventRegistrationToken token);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_ParentWindow )(
+ ICoreWebView2Controller3 * This,
+ /* [retval][out] */ HWND *parentWindow);
+
+ /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_ParentWindow )(
+ ICoreWebView2Controller3 * This,
+ /* [in] */ HWND parentWindow);
+
+ HRESULT ( STDMETHODCALLTYPE *NotifyParentWindowPositionChanged )(
+ ICoreWebView2Controller3 * This);
+
+ HRESULT ( STDMETHODCALLTYPE *Close )(
+ ICoreWebView2Controller3 * This);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_CoreWebView2 )(
+ ICoreWebView2Controller3 * This,
+ /* [retval][out] */ ICoreWebView2 **coreWebView2);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_DefaultBackgroundColor )(
+ ICoreWebView2Controller3 * This,
+ /* [retval][out] */ COREWEBVIEW2_COLOR *backgroundColor);
+
+ /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_DefaultBackgroundColor )(
+ ICoreWebView2Controller3 * This,
+ /* [in] */ COREWEBVIEW2_COLOR backgroundColor);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_RasterizationScale )(
+ ICoreWebView2Controller3 * This,
+ /* [retval][out] */ double *scale);
+
+ /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_RasterizationScale )(
+ ICoreWebView2Controller3 * This,
+ /* [in] */ double scale);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_ShouldDetectMonitorScaleChanges )(
+ ICoreWebView2Controller3 * This,
+ /* [retval][out] */ BOOL *value);
+
+ /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_ShouldDetectMonitorScaleChanges )(
+ ICoreWebView2Controller3 * This,
+ /* [in] */ BOOL value);
+
+ HRESULT ( STDMETHODCALLTYPE *add_RasterizationScaleChanged )(
+ ICoreWebView2Controller3 * This,
+ /* [in] */ ICoreWebView2RasterizationScaleChangedEventHandler *eventHandler,
+ /* [out] */ EventRegistrationToken *token);
+
+ HRESULT ( STDMETHODCALLTYPE *remove_RasterizationScaleChanged )(
+ ICoreWebView2Controller3 * This,
+ /* [in] */ EventRegistrationToken token);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_BoundsMode )(
+ ICoreWebView2Controller3 * This,
+ /* [retval][out] */ COREWEBVIEW2_BOUNDS_MODE *boundsMode);
+
+ /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_BoundsMode )(
+ ICoreWebView2Controller3 * This,
+ /* [in] */ COREWEBVIEW2_BOUNDS_MODE boundsMode);
+
+ END_INTERFACE
+ } ICoreWebView2Controller3Vtbl;
+
+ interface ICoreWebView2Controller3
+ {
+ CONST_VTBL struct ICoreWebView2Controller3Vtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define ICoreWebView2Controller3_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define ICoreWebView2Controller3_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define ICoreWebView2Controller3_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define ICoreWebView2Controller3_get_IsVisible(This,isVisible) \
+ ( (This)->lpVtbl -> get_IsVisible(This,isVisible) )
+
+#define ICoreWebView2Controller3_put_IsVisible(This,isVisible) \
+ ( (This)->lpVtbl -> put_IsVisible(This,isVisible) )
+
+#define ICoreWebView2Controller3_get_Bounds(This,bounds) \
+ ( (This)->lpVtbl -> get_Bounds(This,bounds) )
+
+#define ICoreWebView2Controller3_put_Bounds(This,bounds) \
+ ( (This)->lpVtbl -> put_Bounds(This,bounds) )
+
+#define ICoreWebView2Controller3_get_ZoomFactor(This,zoomFactor) \
+ ( (This)->lpVtbl -> get_ZoomFactor(This,zoomFactor) )
+
+#define ICoreWebView2Controller3_put_ZoomFactor(This,zoomFactor) \
+ ( (This)->lpVtbl -> put_ZoomFactor(This,zoomFactor) )
+
+#define ICoreWebView2Controller3_add_ZoomFactorChanged(This,eventHandler,token) \
+ ( (This)->lpVtbl -> add_ZoomFactorChanged(This,eventHandler,token) )
+
+#define ICoreWebView2Controller3_remove_ZoomFactorChanged(This,token) \
+ ( (This)->lpVtbl -> remove_ZoomFactorChanged(This,token) )
+
+#define ICoreWebView2Controller3_SetBoundsAndZoomFactor(This,bounds,zoomFactor) \
+ ( (This)->lpVtbl -> SetBoundsAndZoomFactor(This,bounds,zoomFactor) )
+
+#define ICoreWebView2Controller3_MoveFocus(This,reason) \
+ ( (This)->lpVtbl -> MoveFocus(This,reason) )
+
+#define ICoreWebView2Controller3_add_MoveFocusRequested(This,eventHandler,token) \
+ ( (This)->lpVtbl -> add_MoveFocusRequested(This,eventHandler,token) )
+
+#define ICoreWebView2Controller3_remove_MoveFocusRequested(This,token) \
+ ( (This)->lpVtbl -> remove_MoveFocusRequested(This,token) )
+
+#define ICoreWebView2Controller3_add_GotFocus(This,eventHandler,token) \
+ ( (This)->lpVtbl -> add_GotFocus(This,eventHandler,token) )
+
+#define ICoreWebView2Controller3_remove_GotFocus(This,token) \
+ ( (This)->lpVtbl -> remove_GotFocus(This,token) )
+
+#define ICoreWebView2Controller3_add_LostFocus(This,eventHandler,token) \
+ ( (This)->lpVtbl -> add_LostFocus(This,eventHandler,token) )
+
+#define ICoreWebView2Controller3_remove_LostFocus(This,token) \
+ ( (This)->lpVtbl -> remove_LostFocus(This,token) )
+
+#define ICoreWebView2Controller3_add_AcceleratorKeyPressed(This,eventHandler,token) \
+ ( (This)->lpVtbl -> add_AcceleratorKeyPressed(This,eventHandler,token) )
+
+#define ICoreWebView2Controller3_remove_AcceleratorKeyPressed(This,token) \
+ ( (This)->lpVtbl -> remove_AcceleratorKeyPressed(This,token) )
+
+#define ICoreWebView2Controller3_get_ParentWindow(This,parentWindow) \
+ ( (This)->lpVtbl -> get_ParentWindow(This,parentWindow) )
+
+#define ICoreWebView2Controller3_put_ParentWindow(This,parentWindow) \
+ ( (This)->lpVtbl -> put_ParentWindow(This,parentWindow) )
+
+#define ICoreWebView2Controller3_NotifyParentWindowPositionChanged(This) \
+ ( (This)->lpVtbl -> NotifyParentWindowPositionChanged(This) )
+
+#define ICoreWebView2Controller3_Close(This) \
+ ( (This)->lpVtbl -> Close(This) )
+
+#define ICoreWebView2Controller3_get_CoreWebView2(This,coreWebView2) \
+ ( (This)->lpVtbl -> get_CoreWebView2(This,coreWebView2) )
+
+
+#define ICoreWebView2Controller3_get_DefaultBackgroundColor(This,backgroundColor) \
+ ( (This)->lpVtbl -> get_DefaultBackgroundColor(This,backgroundColor) )
+
+#define ICoreWebView2Controller3_put_DefaultBackgroundColor(This,backgroundColor) \
+ ( (This)->lpVtbl -> put_DefaultBackgroundColor(This,backgroundColor) )
+
+
+#define ICoreWebView2Controller3_get_RasterizationScale(This,scale) \
+ ( (This)->lpVtbl -> get_RasterizationScale(This,scale) )
+
+#define ICoreWebView2Controller3_put_RasterizationScale(This,scale) \
+ ( (This)->lpVtbl -> put_RasterizationScale(This,scale) )
+
+#define ICoreWebView2Controller3_get_ShouldDetectMonitorScaleChanges(This,value) \
+ ( (This)->lpVtbl -> get_ShouldDetectMonitorScaleChanges(This,value) )
+
+#define ICoreWebView2Controller3_put_ShouldDetectMonitorScaleChanges(This,value) \
+ ( (This)->lpVtbl -> put_ShouldDetectMonitorScaleChanges(This,value) )
+
+#define ICoreWebView2Controller3_add_RasterizationScaleChanged(This,eventHandler,token) \
+ ( (This)->lpVtbl -> add_RasterizationScaleChanged(This,eventHandler,token) )
+
+#define ICoreWebView2Controller3_remove_RasterizationScaleChanged(This,token) \
+ ( (This)->lpVtbl -> remove_RasterizationScaleChanged(This,token) )
+
+#define ICoreWebView2Controller3_get_BoundsMode(This,boundsMode) \
+ ( (This)->lpVtbl -> get_BoundsMode(This,boundsMode) )
+
+#define ICoreWebView2Controller3_put_BoundsMode(This,boundsMode) \
+ ( (This)->lpVtbl -> put_BoundsMode(This,boundsMode) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __ICoreWebView2Controller3_INTERFACE_DEFINED__ */
+
+
+#ifndef __ICoreWebView2ContentLoadingEventArgs_INTERFACE_DEFINED__
+#define __ICoreWebView2ContentLoadingEventArgs_INTERFACE_DEFINED__
+
+/* interface ICoreWebView2ContentLoadingEventArgs */
+/* [unique][object][uuid] */
+
+
+EXTERN_C __declspec(selectany) const IID IID_ICoreWebView2ContentLoadingEventArgs = {0x0c8a1275,0x9b6b,0x4901,{0x87,0xad,0x70,0xdf,0x25,0xba,0xfa,0x6e}};
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("0c8a1275-9b6b-4901-87ad-70df25bafa6e")
+ ICoreWebView2ContentLoadingEventArgs : public IUnknown
+ {
+ public:
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_IsErrorPage(
+ /* [retval][out] */ BOOL *isErrorPage) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_NavigationId(
+ /* [retval][out] */ UINT64 *navigationId) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct ICoreWebView2ContentLoadingEventArgsVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ ICoreWebView2ContentLoadingEventArgs * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ ICoreWebView2ContentLoadingEventArgs * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ ICoreWebView2ContentLoadingEventArgs * This);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_IsErrorPage )(
+ ICoreWebView2ContentLoadingEventArgs * This,
+ /* [retval][out] */ BOOL *isErrorPage);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_NavigationId )(
+ ICoreWebView2ContentLoadingEventArgs * This,
+ /* [retval][out] */ UINT64 *navigationId);
+
+ END_INTERFACE
+ } ICoreWebView2ContentLoadingEventArgsVtbl;
+
+ interface ICoreWebView2ContentLoadingEventArgs
+ {
+ CONST_VTBL struct ICoreWebView2ContentLoadingEventArgsVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define ICoreWebView2ContentLoadingEventArgs_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define ICoreWebView2ContentLoadingEventArgs_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define ICoreWebView2ContentLoadingEventArgs_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define ICoreWebView2ContentLoadingEventArgs_get_IsErrorPage(This,isErrorPage) \
+ ( (This)->lpVtbl -> get_IsErrorPage(This,isErrorPage) )
+
+#define ICoreWebView2ContentLoadingEventArgs_get_NavigationId(This,navigationId) \
+ ( (This)->lpVtbl -> get_NavigationId(This,navigationId) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __ICoreWebView2ContentLoadingEventArgs_INTERFACE_DEFINED__ */
+
+
+#ifndef __ICoreWebView2ContentLoadingEventHandler_INTERFACE_DEFINED__
+#define __ICoreWebView2ContentLoadingEventHandler_INTERFACE_DEFINED__
+
+/* interface ICoreWebView2ContentLoadingEventHandler */
+/* [unique][object][uuid] */
+
+
+EXTERN_C __declspec(selectany) const IID IID_ICoreWebView2ContentLoadingEventHandler = {0x364471e7,0xf2be,0x4910,{0xbd,0xba,0xd7,0x20,0x77,0xd5,0x1c,0x4b}};
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("364471e7-f2be-4910-bdba-d72077d51c4b")
+ ICoreWebView2ContentLoadingEventHandler : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE Invoke(
+ /* [in] */ ICoreWebView2 *sender,
+ /* [in] */ ICoreWebView2ContentLoadingEventArgs *args) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct ICoreWebView2ContentLoadingEventHandlerVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ ICoreWebView2ContentLoadingEventHandler * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ ICoreWebView2ContentLoadingEventHandler * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ ICoreWebView2ContentLoadingEventHandler * This);
+
+ HRESULT ( STDMETHODCALLTYPE *Invoke )(
+ ICoreWebView2ContentLoadingEventHandler * This,
+ /* [in] */ ICoreWebView2 *sender,
+ /* [in] */ ICoreWebView2ContentLoadingEventArgs *args);
+
+ END_INTERFACE
+ } ICoreWebView2ContentLoadingEventHandlerVtbl;
+
+ interface ICoreWebView2ContentLoadingEventHandler
+ {
+ CONST_VTBL struct ICoreWebView2ContentLoadingEventHandlerVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define ICoreWebView2ContentLoadingEventHandler_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define ICoreWebView2ContentLoadingEventHandler_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define ICoreWebView2ContentLoadingEventHandler_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define ICoreWebView2ContentLoadingEventHandler_Invoke(This,sender,args) \
+ ( (This)->lpVtbl -> Invoke(This,sender,args) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __ICoreWebView2ContentLoadingEventHandler_INTERFACE_DEFINED__ */
+
+
+#ifndef __ICoreWebView2Cookie_INTERFACE_DEFINED__
+#define __ICoreWebView2Cookie_INTERFACE_DEFINED__
+
+/* interface ICoreWebView2Cookie */
+/* [unique][object][uuid] */
+
+
+EXTERN_C __declspec(selectany) const IID IID_ICoreWebView2Cookie = {0xAD26D6BE,0x1486,0x43E6,{0xBF,0x87,0xA2,0x03,0x40,0x06,0xCA,0x21}};
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("AD26D6BE-1486-43E6-BF87-A2034006CA21")
+ ICoreWebView2Cookie : public IUnknown
+ {
+ public:
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_Name(
+ /* [retval][out] */ LPWSTR *name) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_Value(
+ /* [retval][out] */ LPWSTR *value) = 0;
+
+ virtual /* [propput] */ HRESULT STDMETHODCALLTYPE put_Value(
+ /* [in] */ LPCWSTR value) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_Domain(
+ /* [retval][out] */ LPWSTR *domain) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_Path(
+ /* [retval][out] */ LPWSTR *path) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_Expires(
+ /* [retval][out] */ double *expires) = 0;
+
+ virtual /* [propput] */ HRESULT STDMETHODCALLTYPE put_Expires(
+ /* [in] */ double expires) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_IsHttpOnly(
+ /* [retval][out] */ BOOL *isHttpOnly) = 0;
+
+ virtual /* [propput] */ HRESULT STDMETHODCALLTYPE put_IsHttpOnly(
+ /* [in] */ BOOL isHttpOnly) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_SameSite(
+ /* [retval][out] */ COREWEBVIEW2_COOKIE_SAME_SITE_KIND *sameSite) = 0;
+
+ virtual /* [propput] */ HRESULT STDMETHODCALLTYPE put_SameSite(
+ /* [in] */ COREWEBVIEW2_COOKIE_SAME_SITE_KIND sameSite) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_IsSecure(
+ /* [retval][out] */ BOOL *isSecure) = 0;
+
+ virtual /* [propput] */ HRESULT STDMETHODCALLTYPE put_IsSecure(
+ /* [in] */ BOOL isSecure) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_IsSession(
+ /* [retval][out] */ BOOL *isSession) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct ICoreWebView2CookieVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ ICoreWebView2Cookie * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ ICoreWebView2Cookie * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ ICoreWebView2Cookie * This);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_Name )(
+ ICoreWebView2Cookie * This,
+ /* [retval][out] */ LPWSTR *name);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_Value )(
+ ICoreWebView2Cookie * This,
+ /* [retval][out] */ LPWSTR *value);
+
+ /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_Value )(
+ ICoreWebView2Cookie * This,
+ /* [in] */ LPCWSTR value);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_Domain )(
+ ICoreWebView2Cookie * This,
+ /* [retval][out] */ LPWSTR *domain);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_Path )(
+ ICoreWebView2Cookie * This,
+ /* [retval][out] */ LPWSTR *path);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_Expires )(
+ ICoreWebView2Cookie * This,
+ /* [retval][out] */ double *expires);
+
+ /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_Expires )(
+ ICoreWebView2Cookie * This,
+ /* [in] */ double expires);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_IsHttpOnly )(
+ ICoreWebView2Cookie * This,
+ /* [retval][out] */ BOOL *isHttpOnly);
+
+ /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_IsHttpOnly )(
+ ICoreWebView2Cookie * This,
+ /* [in] */ BOOL isHttpOnly);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_SameSite )(
+ ICoreWebView2Cookie * This,
+ /* [retval][out] */ COREWEBVIEW2_COOKIE_SAME_SITE_KIND *sameSite);
+
+ /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_SameSite )(
+ ICoreWebView2Cookie * This,
+ /* [in] */ COREWEBVIEW2_COOKIE_SAME_SITE_KIND sameSite);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_IsSecure )(
+ ICoreWebView2Cookie * This,
+ /* [retval][out] */ BOOL *isSecure);
+
+ /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_IsSecure )(
+ ICoreWebView2Cookie * This,
+ /* [in] */ BOOL isSecure);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_IsSession )(
+ ICoreWebView2Cookie * This,
+ /* [retval][out] */ BOOL *isSession);
+
+ END_INTERFACE
+ } ICoreWebView2CookieVtbl;
+
+ interface ICoreWebView2Cookie
+ {
+ CONST_VTBL struct ICoreWebView2CookieVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define ICoreWebView2Cookie_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define ICoreWebView2Cookie_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define ICoreWebView2Cookie_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define ICoreWebView2Cookie_get_Name(This,name) \
+ ( (This)->lpVtbl -> get_Name(This,name) )
+
+#define ICoreWebView2Cookie_get_Value(This,value) \
+ ( (This)->lpVtbl -> get_Value(This,value) )
+
+#define ICoreWebView2Cookie_put_Value(This,value) \
+ ( (This)->lpVtbl -> put_Value(This,value) )
+
+#define ICoreWebView2Cookie_get_Domain(This,domain) \
+ ( (This)->lpVtbl -> get_Domain(This,domain) )
+
+#define ICoreWebView2Cookie_get_Path(This,path) \
+ ( (This)->lpVtbl -> get_Path(This,path) )
+
+#define ICoreWebView2Cookie_get_Expires(This,expires) \
+ ( (This)->lpVtbl -> get_Expires(This,expires) )
+
+#define ICoreWebView2Cookie_put_Expires(This,expires) \
+ ( (This)->lpVtbl -> put_Expires(This,expires) )
+
+#define ICoreWebView2Cookie_get_IsHttpOnly(This,isHttpOnly) \
+ ( (This)->lpVtbl -> get_IsHttpOnly(This,isHttpOnly) )
+
+#define ICoreWebView2Cookie_put_IsHttpOnly(This,isHttpOnly) \
+ ( (This)->lpVtbl -> put_IsHttpOnly(This,isHttpOnly) )
+
+#define ICoreWebView2Cookie_get_SameSite(This,sameSite) \
+ ( (This)->lpVtbl -> get_SameSite(This,sameSite) )
+
+#define ICoreWebView2Cookie_put_SameSite(This,sameSite) \
+ ( (This)->lpVtbl -> put_SameSite(This,sameSite) )
+
+#define ICoreWebView2Cookie_get_IsSecure(This,isSecure) \
+ ( (This)->lpVtbl -> get_IsSecure(This,isSecure) )
+
+#define ICoreWebView2Cookie_put_IsSecure(This,isSecure) \
+ ( (This)->lpVtbl -> put_IsSecure(This,isSecure) )
+
+#define ICoreWebView2Cookie_get_IsSession(This,isSession) \
+ ( (This)->lpVtbl -> get_IsSession(This,isSession) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __ICoreWebView2Cookie_INTERFACE_DEFINED__ */
+
+
+#ifndef __ICoreWebView2CookieList_INTERFACE_DEFINED__
+#define __ICoreWebView2CookieList_INTERFACE_DEFINED__
+
+/* interface ICoreWebView2CookieList */
+/* [unique][object][uuid] */
+
+
+EXTERN_C __declspec(selectany) const IID IID_ICoreWebView2CookieList = {0xF7F6F714,0x5D2A,0x43C6,{0x95,0x03,0x34,0x6E,0xCE,0x02,0xD1,0x86}};
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("F7F6F714-5D2A-43C6-9503-346ECE02D186")
+ ICoreWebView2CookieList : public IUnknown
+ {
+ public:
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_Count(
+ /* [retval][out] */ UINT *count) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetValueAtIndex(
+ /* [in] */ UINT index,
+ /* [retval][out] */ ICoreWebView2Cookie **cookie) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct ICoreWebView2CookieListVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ ICoreWebView2CookieList * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ ICoreWebView2CookieList * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ ICoreWebView2CookieList * This);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_Count )(
+ ICoreWebView2CookieList * This,
+ /* [retval][out] */ UINT *count);
+
+ HRESULT ( STDMETHODCALLTYPE *GetValueAtIndex )(
+ ICoreWebView2CookieList * This,
+ /* [in] */ UINT index,
+ /* [retval][out] */ ICoreWebView2Cookie **cookie);
+
+ END_INTERFACE
+ } ICoreWebView2CookieListVtbl;
+
+ interface ICoreWebView2CookieList
+ {
+ CONST_VTBL struct ICoreWebView2CookieListVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define ICoreWebView2CookieList_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define ICoreWebView2CookieList_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define ICoreWebView2CookieList_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define ICoreWebView2CookieList_get_Count(This,count) \
+ ( (This)->lpVtbl -> get_Count(This,count) )
+
+#define ICoreWebView2CookieList_GetValueAtIndex(This,index,cookie) \
+ ( (This)->lpVtbl -> GetValueAtIndex(This,index,cookie) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __ICoreWebView2CookieList_INTERFACE_DEFINED__ */
+
+
+#ifndef __ICoreWebView2CookieManager_INTERFACE_DEFINED__
+#define __ICoreWebView2CookieManager_INTERFACE_DEFINED__
+
+/* interface ICoreWebView2CookieManager */
+/* [unique][object][uuid] */
+
+
+EXTERN_C __declspec(selectany) const IID IID_ICoreWebView2CookieManager = {0x177CD9E7,0xB6F5,0x451A,{0x94,0xA0,0x5D,0x7A,0x3A,0x4C,0x41,0x41}};
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("177CD9E7-B6F5-451A-94A0-5D7A3A4C4141")
+ ICoreWebView2CookieManager : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE CreateCookie(
+ /* [in] */ LPCWSTR name,
+ /* [in] */ LPCWSTR value,
+ /* [in] */ LPCWSTR domain,
+ /* [in] */ LPCWSTR path,
+ /* [retval][out] */ ICoreWebView2Cookie **cookie) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE CopyCookie(
+ /* [in] */ ICoreWebView2Cookie *cookieParam,
+ /* [retval][out] */ ICoreWebView2Cookie **cookie) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetCookies(
+ /* [in] */ LPCWSTR uri,
+ /* [in] */ ICoreWebView2GetCookiesCompletedHandler *handler) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE AddOrUpdateCookie(
+ /* [in] */ ICoreWebView2Cookie *cookie) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE DeleteCookie(
+ /* [in] */ ICoreWebView2Cookie *cookie) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE DeleteCookies(
+ /* [in] */ LPCWSTR name,
+ /* [in] */ LPCWSTR uri) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE DeleteCookiesWithDomainAndPath(
+ /* [in] */ LPCWSTR name,
+ /* [in] */ LPCWSTR domain,
+ /* [in] */ LPCWSTR path) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE DeleteAllCookies( void) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct ICoreWebView2CookieManagerVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ ICoreWebView2CookieManager * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ ICoreWebView2CookieManager * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ ICoreWebView2CookieManager * This);
+
+ HRESULT ( STDMETHODCALLTYPE *CreateCookie )(
+ ICoreWebView2CookieManager * This,
+ /* [in] */ LPCWSTR name,
+ /* [in] */ LPCWSTR value,
+ /* [in] */ LPCWSTR domain,
+ /* [in] */ LPCWSTR path,
+ /* [retval][out] */ ICoreWebView2Cookie **cookie);
+
+ HRESULT ( STDMETHODCALLTYPE *CopyCookie )(
+ ICoreWebView2CookieManager * This,
+ /* [in] */ ICoreWebView2Cookie *cookieParam,
+ /* [retval][out] */ ICoreWebView2Cookie **cookie);
+
+ HRESULT ( STDMETHODCALLTYPE *GetCookies )(
+ ICoreWebView2CookieManager * This,
+ /* [in] */ LPCWSTR uri,
+ /* [in] */ ICoreWebView2GetCookiesCompletedHandler *handler);
+
+ HRESULT ( STDMETHODCALLTYPE *AddOrUpdateCookie )(
+ ICoreWebView2CookieManager * This,
+ /* [in] */ ICoreWebView2Cookie *cookie);
+
+ HRESULT ( STDMETHODCALLTYPE *DeleteCookie )(
+ ICoreWebView2CookieManager * This,
+ /* [in] */ ICoreWebView2Cookie *cookie);
+
+ HRESULT ( STDMETHODCALLTYPE *DeleteCookies )(
+ ICoreWebView2CookieManager * This,
+ /* [in] */ LPCWSTR name,
+ /* [in] */ LPCWSTR uri);
+
+ HRESULT ( STDMETHODCALLTYPE *DeleteCookiesWithDomainAndPath )(
+ ICoreWebView2CookieManager * This,
+ /* [in] */ LPCWSTR name,
+ /* [in] */ LPCWSTR domain,
+ /* [in] */ LPCWSTR path);
+
+ HRESULT ( STDMETHODCALLTYPE *DeleteAllCookies )(
+ ICoreWebView2CookieManager * This);
+
+ END_INTERFACE
+ } ICoreWebView2CookieManagerVtbl;
+
+ interface ICoreWebView2CookieManager
+ {
+ CONST_VTBL struct ICoreWebView2CookieManagerVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define ICoreWebView2CookieManager_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define ICoreWebView2CookieManager_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define ICoreWebView2CookieManager_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define ICoreWebView2CookieManager_CreateCookie(This,name,value,domain,path,cookie) \
+ ( (This)->lpVtbl -> CreateCookie(This,name,value,domain,path,cookie) )
+
+#define ICoreWebView2CookieManager_CopyCookie(This,cookieParam,cookie) \
+ ( (This)->lpVtbl -> CopyCookie(This,cookieParam,cookie) )
+
+#define ICoreWebView2CookieManager_GetCookies(This,uri,handler) \
+ ( (This)->lpVtbl -> GetCookies(This,uri,handler) )
+
+#define ICoreWebView2CookieManager_AddOrUpdateCookie(This,cookie) \
+ ( (This)->lpVtbl -> AddOrUpdateCookie(This,cookie) )
+
+#define ICoreWebView2CookieManager_DeleteCookie(This,cookie) \
+ ( (This)->lpVtbl -> DeleteCookie(This,cookie) )
+
+#define ICoreWebView2CookieManager_DeleteCookies(This,name,uri) \
+ ( (This)->lpVtbl -> DeleteCookies(This,name,uri) )
+
+#define ICoreWebView2CookieManager_DeleteCookiesWithDomainAndPath(This,name,domain,path) \
+ ( (This)->lpVtbl -> DeleteCookiesWithDomainAndPath(This,name,domain,path) )
+
+#define ICoreWebView2CookieManager_DeleteAllCookies(This) \
+ ( (This)->lpVtbl -> DeleteAllCookies(This) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __ICoreWebView2CookieManager_INTERFACE_DEFINED__ */
+
+
+#ifndef __ICoreWebView2CreateCoreWebView2CompositionControllerCompletedHandler_INTERFACE_DEFINED__
+#define __ICoreWebView2CreateCoreWebView2CompositionControllerCompletedHandler_INTERFACE_DEFINED__
+
+/* interface ICoreWebView2CreateCoreWebView2CompositionControllerCompletedHandler */
+/* [unique][object][uuid] */
+
+
+EXTERN_C __declspec(selectany) const IID IID_ICoreWebView2CreateCoreWebView2CompositionControllerCompletedHandler = {0x02fab84b,0x1428,0x4fb7,{0xad,0x45,0x1b,0x2e,0x64,0x73,0x61,0x84}};
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("02fab84b-1428-4fb7-ad45-1b2e64736184")
+ ICoreWebView2CreateCoreWebView2CompositionControllerCompletedHandler : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE Invoke(
+ HRESULT errorCode,
+ ICoreWebView2CompositionController *webView) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct ICoreWebView2CreateCoreWebView2CompositionControllerCompletedHandlerVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ ICoreWebView2CreateCoreWebView2CompositionControllerCompletedHandler * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ ICoreWebView2CreateCoreWebView2CompositionControllerCompletedHandler * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ ICoreWebView2CreateCoreWebView2CompositionControllerCompletedHandler * This);
+
+ HRESULT ( STDMETHODCALLTYPE *Invoke )(
+ ICoreWebView2CreateCoreWebView2CompositionControllerCompletedHandler * This,
+ HRESULT errorCode,
+ ICoreWebView2CompositionController *webView);
+
+ END_INTERFACE
+ } ICoreWebView2CreateCoreWebView2CompositionControllerCompletedHandlerVtbl;
+
+ interface ICoreWebView2CreateCoreWebView2CompositionControllerCompletedHandler
+ {
+ CONST_VTBL struct ICoreWebView2CreateCoreWebView2CompositionControllerCompletedHandlerVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define ICoreWebView2CreateCoreWebView2CompositionControllerCompletedHandler_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define ICoreWebView2CreateCoreWebView2CompositionControllerCompletedHandler_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define ICoreWebView2CreateCoreWebView2CompositionControllerCompletedHandler_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define ICoreWebView2CreateCoreWebView2CompositionControllerCompletedHandler_Invoke(This,errorCode,webView) \
+ ( (This)->lpVtbl -> Invoke(This,errorCode,webView) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __ICoreWebView2CreateCoreWebView2CompositionControllerCompletedHandler_INTERFACE_DEFINED__ */
+
+
+#ifndef __ICoreWebView2CreateCoreWebView2ControllerCompletedHandler_INTERFACE_DEFINED__
+#define __ICoreWebView2CreateCoreWebView2ControllerCompletedHandler_INTERFACE_DEFINED__
+
+/* interface ICoreWebView2CreateCoreWebView2ControllerCompletedHandler */
+/* [unique][object][uuid] */
+
+
+EXTERN_C __declspec(selectany) const IID IID_ICoreWebView2CreateCoreWebView2ControllerCompletedHandler = {0x6c4819f3,0xc9b7,0x4260,{0x81,0x27,0xc9,0xf5,0xbd,0xe7,0xf6,0x8c}};
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("6c4819f3-c9b7-4260-8127-c9f5bde7f68c")
+ ICoreWebView2CreateCoreWebView2ControllerCompletedHandler : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE Invoke(
+ HRESULT errorCode,
+ ICoreWebView2Controller *createdController) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct ICoreWebView2CreateCoreWebView2ControllerCompletedHandlerVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ ICoreWebView2CreateCoreWebView2ControllerCompletedHandler * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ ICoreWebView2CreateCoreWebView2ControllerCompletedHandler * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ ICoreWebView2CreateCoreWebView2ControllerCompletedHandler * This);
+
+ HRESULT ( STDMETHODCALLTYPE *Invoke )(
+ ICoreWebView2CreateCoreWebView2ControllerCompletedHandler * This,
+ HRESULT errorCode,
+ ICoreWebView2Controller *createdController);
+
+ END_INTERFACE
+ } ICoreWebView2CreateCoreWebView2ControllerCompletedHandlerVtbl;
+
+ interface ICoreWebView2CreateCoreWebView2ControllerCompletedHandler
+ {
+ CONST_VTBL struct ICoreWebView2CreateCoreWebView2ControllerCompletedHandlerVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define ICoreWebView2CreateCoreWebView2ControllerCompletedHandler_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define ICoreWebView2CreateCoreWebView2ControllerCompletedHandler_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define ICoreWebView2CreateCoreWebView2ControllerCompletedHandler_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define ICoreWebView2CreateCoreWebView2ControllerCompletedHandler_Invoke(This,errorCode,createdController) \
+ ( (This)->lpVtbl -> Invoke(This,errorCode,createdController) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __ICoreWebView2CreateCoreWebView2ControllerCompletedHandler_INTERFACE_DEFINED__ */
+
+
+#ifndef __ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler_INTERFACE_DEFINED__
+#define __ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler_INTERFACE_DEFINED__
+
+/* interface ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler */
+/* [unique][object][uuid] */
+
+
+EXTERN_C __declspec(selectany) const IID IID_ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler = {0x4e8a3389,0xc9d8,0x4bd2,{0xb6,0xb5,0x12,0x4f,0xee,0x6c,0xc1,0x4d}};
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("4e8a3389-c9d8-4bd2-b6b5-124fee6cc14d")
+ ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE Invoke(
+ HRESULT errorCode,
+ ICoreWebView2Environment *createdEnvironment) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandlerVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler * This);
+
+ HRESULT ( STDMETHODCALLTYPE *Invoke )(
+ ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler * This,
+ HRESULT errorCode,
+ ICoreWebView2Environment *createdEnvironment);
+
+ END_INTERFACE
+ } ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandlerVtbl;
+
+ interface ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler
+ {
+ CONST_VTBL struct ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandlerVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler_Invoke(This,errorCode,createdEnvironment) \
+ ( (This)->lpVtbl -> Invoke(This,errorCode,createdEnvironment) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler_INTERFACE_DEFINED__ */
+
+
+#ifndef __ICoreWebView2ContainsFullScreenElementChangedEventHandler_INTERFACE_DEFINED__
+#define __ICoreWebView2ContainsFullScreenElementChangedEventHandler_INTERFACE_DEFINED__
+
+/* interface ICoreWebView2ContainsFullScreenElementChangedEventHandler */
+/* [unique][object][uuid] */
+
+
+EXTERN_C __declspec(selectany) const IID IID_ICoreWebView2ContainsFullScreenElementChangedEventHandler = {0xe45d98b1,0xafef,0x45be,{0x8b,0xaf,0x6c,0x77,0x28,0x86,0x7f,0x73}};
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("e45d98b1-afef-45be-8baf-6c7728867f73")
+ ICoreWebView2ContainsFullScreenElementChangedEventHandler : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE Invoke(
+ /* [in] */ ICoreWebView2 *sender,
+ /* [in] */ IUnknown *args) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct ICoreWebView2ContainsFullScreenElementChangedEventHandlerVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ ICoreWebView2ContainsFullScreenElementChangedEventHandler * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ ICoreWebView2ContainsFullScreenElementChangedEventHandler * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ ICoreWebView2ContainsFullScreenElementChangedEventHandler * This);
+
+ HRESULT ( STDMETHODCALLTYPE *Invoke )(
+ ICoreWebView2ContainsFullScreenElementChangedEventHandler * This,
+ /* [in] */ ICoreWebView2 *sender,
+ /* [in] */ IUnknown *args);
+
+ END_INTERFACE
+ } ICoreWebView2ContainsFullScreenElementChangedEventHandlerVtbl;
+
+ interface ICoreWebView2ContainsFullScreenElementChangedEventHandler
+ {
+ CONST_VTBL struct ICoreWebView2ContainsFullScreenElementChangedEventHandlerVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define ICoreWebView2ContainsFullScreenElementChangedEventHandler_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define ICoreWebView2ContainsFullScreenElementChangedEventHandler_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define ICoreWebView2ContainsFullScreenElementChangedEventHandler_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define ICoreWebView2ContainsFullScreenElementChangedEventHandler_Invoke(This,sender,args) \
+ ( (This)->lpVtbl -> Invoke(This,sender,args) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __ICoreWebView2ContainsFullScreenElementChangedEventHandler_INTERFACE_DEFINED__ */
+
+
+#ifndef __ICoreWebView2CursorChangedEventHandler_INTERFACE_DEFINED__
+#define __ICoreWebView2CursorChangedEventHandler_INTERFACE_DEFINED__
+
+/* interface ICoreWebView2CursorChangedEventHandler */
+/* [unique][object][uuid] */
+
+
+EXTERN_C __declspec(selectany) const IID IID_ICoreWebView2CursorChangedEventHandler = {0x9da43ccc,0x26e1,0x4dad,{0xb5,0x6c,0xd8,0x96,0x1c,0x94,0xc5,0x71}};
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("9da43ccc-26e1-4dad-b56c-d8961c94c571")
+ ICoreWebView2CursorChangedEventHandler : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE Invoke(
+ /* [in] */ ICoreWebView2CompositionController *sender,
+ /* [in] */ IUnknown *args) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct ICoreWebView2CursorChangedEventHandlerVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ ICoreWebView2CursorChangedEventHandler * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ ICoreWebView2CursorChangedEventHandler * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ ICoreWebView2CursorChangedEventHandler * This);
+
+ HRESULT ( STDMETHODCALLTYPE *Invoke )(
+ ICoreWebView2CursorChangedEventHandler * This,
+ /* [in] */ ICoreWebView2CompositionController *sender,
+ /* [in] */ IUnknown *args);
+
+ END_INTERFACE
+ } ICoreWebView2CursorChangedEventHandlerVtbl;
+
+ interface ICoreWebView2CursorChangedEventHandler
+ {
+ CONST_VTBL struct ICoreWebView2CursorChangedEventHandlerVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define ICoreWebView2CursorChangedEventHandler_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define ICoreWebView2CursorChangedEventHandler_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define ICoreWebView2CursorChangedEventHandler_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define ICoreWebView2CursorChangedEventHandler_Invoke(This,sender,args) \
+ ( (This)->lpVtbl -> Invoke(This,sender,args) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __ICoreWebView2CursorChangedEventHandler_INTERFACE_DEFINED__ */
+
+
+#ifndef __ICoreWebView2DocumentTitleChangedEventHandler_INTERFACE_DEFINED__
+#define __ICoreWebView2DocumentTitleChangedEventHandler_INTERFACE_DEFINED__
+
+/* interface ICoreWebView2DocumentTitleChangedEventHandler */
+/* [unique][object][uuid] */
+
+
+EXTERN_C __declspec(selectany) const IID IID_ICoreWebView2DocumentTitleChangedEventHandler = {0xf5f2b923,0x953e,0x4042,{0x9f,0x95,0xf3,0xa1,0x18,0xe1,0xaf,0xd4}};
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("f5f2b923-953e-4042-9f95-f3a118e1afd4")
+ ICoreWebView2DocumentTitleChangedEventHandler : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE Invoke(
+ /* [in] */ ICoreWebView2 *sender,
+ /* [in] */ IUnknown *args) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct ICoreWebView2DocumentTitleChangedEventHandlerVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ ICoreWebView2DocumentTitleChangedEventHandler * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ ICoreWebView2DocumentTitleChangedEventHandler * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ ICoreWebView2DocumentTitleChangedEventHandler * This);
+
+ HRESULT ( STDMETHODCALLTYPE *Invoke )(
+ ICoreWebView2DocumentTitleChangedEventHandler * This,
+ /* [in] */ ICoreWebView2 *sender,
+ /* [in] */ IUnknown *args);
+
+ END_INTERFACE
+ } ICoreWebView2DocumentTitleChangedEventHandlerVtbl;
+
+ interface ICoreWebView2DocumentTitleChangedEventHandler
+ {
+ CONST_VTBL struct ICoreWebView2DocumentTitleChangedEventHandlerVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define ICoreWebView2DocumentTitleChangedEventHandler_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define ICoreWebView2DocumentTitleChangedEventHandler_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define ICoreWebView2DocumentTitleChangedEventHandler_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define ICoreWebView2DocumentTitleChangedEventHandler_Invoke(This,sender,args) \
+ ( (This)->lpVtbl -> Invoke(This,sender,args) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __ICoreWebView2DocumentTitleChangedEventHandler_INTERFACE_DEFINED__ */
+
+
+#ifndef __ICoreWebView2DOMContentLoadedEventArgs_INTERFACE_DEFINED__
+#define __ICoreWebView2DOMContentLoadedEventArgs_INTERFACE_DEFINED__
+
+/* interface ICoreWebView2DOMContentLoadedEventArgs */
+/* [unique][object][uuid] */
+
+
+EXTERN_C __declspec(selectany) const IID IID_ICoreWebView2DOMContentLoadedEventArgs = {0x16B1E21A,0xC503,0x44F2,{0x84,0xC9,0x70,0xAB,0xA5,0x03,0x12,0x83}};
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("16B1E21A-C503-44F2-84C9-70ABA5031283")
+ ICoreWebView2DOMContentLoadedEventArgs : public IUnknown
+ {
+ public:
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_NavigationId(
+ /* [retval][out] */ UINT64 *navigationId) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct ICoreWebView2DOMContentLoadedEventArgsVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ ICoreWebView2DOMContentLoadedEventArgs * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ ICoreWebView2DOMContentLoadedEventArgs * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ ICoreWebView2DOMContentLoadedEventArgs * This);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_NavigationId )(
+ ICoreWebView2DOMContentLoadedEventArgs * This,
+ /* [retval][out] */ UINT64 *navigationId);
+
+ END_INTERFACE
+ } ICoreWebView2DOMContentLoadedEventArgsVtbl;
+
+ interface ICoreWebView2DOMContentLoadedEventArgs
+ {
+ CONST_VTBL struct ICoreWebView2DOMContentLoadedEventArgsVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define ICoreWebView2DOMContentLoadedEventArgs_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define ICoreWebView2DOMContentLoadedEventArgs_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define ICoreWebView2DOMContentLoadedEventArgs_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define ICoreWebView2DOMContentLoadedEventArgs_get_NavigationId(This,navigationId) \
+ ( (This)->lpVtbl -> get_NavigationId(This,navigationId) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __ICoreWebView2DOMContentLoadedEventArgs_INTERFACE_DEFINED__ */
+
+
+#ifndef __ICoreWebView2DOMContentLoadedEventHandler_INTERFACE_DEFINED__
+#define __ICoreWebView2DOMContentLoadedEventHandler_INTERFACE_DEFINED__
+
+/* interface ICoreWebView2DOMContentLoadedEventHandler */
+/* [unique][object][uuid] */
+
+
+EXTERN_C __declspec(selectany) const IID IID_ICoreWebView2DOMContentLoadedEventHandler = {0x4BAC7E9C,0x199E,0x49ED,{0x87,0xED,0x24,0x93,0x03,0xAC,0xF0,0x19}};
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("4BAC7E9C-199E-49ED-87ED-249303ACF019")
+ ICoreWebView2DOMContentLoadedEventHandler : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE Invoke(
+ /* [in] */ ICoreWebView2 *sender,
+ /* [in] */ ICoreWebView2DOMContentLoadedEventArgs *args) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct ICoreWebView2DOMContentLoadedEventHandlerVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ ICoreWebView2DOMContentLoadedEventHandler * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ ICoreWebView2DOMContentLoadedEventHandler * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ ICoreWebView2DOMContentLoadedEventHandler * This);
+
+ HRESULT ( STDMETHODCALLTYPE *Invoke )(
+ ICoreWebView2DOMContentLoadedEventHandler * This,
+ /* [in] */ ICoreWebView2 *sender,
+ /* [in] */ ICoreWebView2DOMContentLoadedEventArgs *args);
+
+ END_INTERFACE
+ } ICoreWebView2DOMContentLoadedEventHandlerVtbl;
+
+ interface ICoreWebView2DOMContentLoadedEventHandler
+ {
+ CONST_VTBL struct ICoreWebView2DOMContentLoadedEventHandlerVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define ICoreWebView2DOMContentLoadedEventHandler_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define ICoreWebView2DOMContentLoadedEventHandler_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define ICoreWebView2DOMContentLoadedEventHandler_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define ICoreWebView2DOMContentLoadedEventHandler_Invoke(This,sender,args) \
+ ( (This)->lpVtbl -> Invoke(This,sender,args) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __ICoreWebView2DOMContentLoadedEventHandler_INTERFACE_DEFINED__ */
+
+
+#ifndef __ICoreWebView2Deferral_INTERFACE_DEFINED__
+#define __ICoreWebView2Deferral_INTERFACE_DEFINED__
+
+/* interface ICoreWebView2Deferral */
+/* [unique][object][uuid] */
+
+
+EXTERN_C __declspec(selectany) const IID IID_ICoreWebView2Deferral = {0xc10e7f7b,0xb585,0x46f0,{0xa6,0x23,0x8b,0xef,0xbf,0x3e,0x4e,0xe0}};
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("c10e7f7b-b585-46f0-a623-8befbf3e4ee0")
+ ICoreWebView2Deferral : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE Complete( void) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct ICoreWebView2DeferralVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ ICoreWebView2Deferral * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ ICoreWebView2Deferral * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ ICoreWebView2Deferral * This);
+
+ HRESULT ( STDMETHODCALLTYPE *Complete )(
+ ICoreWebView2Deferral * This);
+
+ END_INTERFACE
+ } ICoreWebView2DeferralVtbl;
+
+ interface ICoreWebView2Deferral
+ {
+ CONST_VTBL struct ICoreWebView2DeferralVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define ICoreWebView2Deferral_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define ICoreWebView2Deferral_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define ICoreWebView2Deferral_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define ICoreWebView2Deferral_Complete(This) \
+ ( (This)->lpVtbl -> Complete(This) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __ICoreWebView2Deferral_INTERFACE_DEFINED__ */
+
+
+#ifndef __ICoreWebView2DevToolsProtocolEventReceivedEventArgs_INTERFACE_DEFINED__
+#define __ICoreWebView2DevToolsProtocolEventReceivedEventArgs_INTERFACE_DEFINED__
+
+/* interface ICoreWebView2DevToolsProtocolEventReceivedEventArgs */
+/* [unique][object][uuid] */
+
+
+EXTERN_C __declspec(selectany) const IID IID_ICoreWebView2DevToolsProtocolEventReceivedEventArgs = {0x653c2959,0xbb3a,0x4377,{0x86,0x32,0xb5,0x8a,0xda,0x4e,0x66,0xc4}};
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("653c2959-bb3a-4377-8632-b58ada4e66c4")
+ ICoreWebView2DevToolsProtocolEventReceivedEventArgs : public IUnknown
+ {
+ public:
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_ParameterObjectAsJson(
+ /* [retval][out] */ LPWSTR *parameterObjectAsJson) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct ICoreWebView2DevToolsProtocolEventReceivedEventArgsVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ ICoreWebView2DevToolsProtocolEventReceivedEventArgs * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ ICoreWebView2DevToolsProtocolEventReceivedEventArgs * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ ICoreWebView2DevToolsProtocolEventReceivedEventArgs * This);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_ParameterObjectAsJson )(
+ ICoreWebView2DevToolsProtocolEventReceivedEventArgs * This,
+ /* [retval][out] */ LPWSTR *parameterObjectAsJson);
+
+ END_INTERFACE
+ } ICoreWebView2DevToolsProtocolEventReceivedEventArgsVtbl;
+
+ interface ICoreWebView2DevToolsProtocolEventReceivedEventArgs
+ {
+ CONST_VTBL struct ICoreWebView2DevToolsProtocolEventReceivedEventArgsVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define ICoreWebView2DevToolsProtocolEventReceivedEventArgs_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define ICoreWebView2DevToolsProtocolEventReceivedEventArgs_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define ICoreWebView2DevToolsProtocolEventReceivedEventArgs_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define ICoreWebView2DevToolsProtocolEventReceivedEventArgs_get_ParameterObjectAsJson(This,parameterObjectAsJson) \
+ ( (This)->lpVtbl -> get_ParameterObjectAsJson(This,parameterObjectAsJson) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __ICoreWebView2DevToolsProtocolEventReceivedEventArgs_INTERFACE_DEFINED__ */
+
+
+#ifndef __ICoreWebView2DevToolsProtocolEventReceivedEventHandler_INTERFACE_DEFINED__
+#define __ICoreWebView2DevToolsProtocolEventReceivedEventHandler_INTERFACE_DEFINED__
+
+/* interface ICoreWebView2DevToolsProtocolEventReceivedEventHandler */
+/* [unique][object][uuid] */
+
+
+EXTERN_C __declspec(selectany) const IID IID_ICoreWebView2DevToolsProtocolEventReceivedEventHandler = {0xe2fda4be,0x5456,0x406c,{0xa2,0x61,0x3d,0x45,0x21,0x38,0x36,0x2c}};
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("e2fda4be-5456-406c-a261-3d452138362c")
+ ICoreWebView2DevToolsProtocolEventReceivedEventHandler : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE Invoke(
+ /* [in] */ ICoreWebView2 *sender,
+ /* [in] */ ICoreWebView2DevToolsProtocolEventReceivedEventArgs *args) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct ICoreWebView2DevToolsProtocolEventReceivedEventHandlerVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ ICoreWebView2DevToolsProtocolEventReceivedEventHandler * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ ICoreWebView2DevToolsProtocolEventReceivedEventHandler * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ ICoreWebView2DevToolsProtocolEventReceivedEventHandler * This);
+
+ HRESULT ( STDMETHODCALLTYPE *Invoke )(
+ ICoreWebView2DevToolsProtocolEventReceivedEventHandler * This,
+ /* [in] */ ICoreWebView2 *sender,
+ /* [in] */ ICoreWebView2DevToolsProtocolEventReceivedEventArgs *args);
+
+ END_INTERFACE
+ } ICoreWebView2DevToolsProtocolEventReceivedEventHandlerVtbl;
+
+ interface ICoreWebView2DevToolsProtocolEventReceivedEventHandler
+ {
+ CONST_VTBL struct ICoreWebView2DevToolsProtocolEventReceivedEventHandlerVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define ICoreWebView2DevToolsProtocolEventReceivedEventHandler_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define ICoreWebView2DevToolsProtocolEventReceivedEventHandler_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define ICoreWebView2DevToolsProtocolEventReceivedEventHandler_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define ICoreWebView2DevToolsProtocolEventReceivedEventHandler_Invoke(This,sender,args) \
+ ( (This)->lpVtbl -> Invoke(This,sender,args) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __ICoreWebView2DevToolsProtocolEventReceivedEventHandler_INTERFACE_DEFINED__ */
+
+
+#ifndef __ICoreWebView2DevToolsProtocolEventReceiver_INTERFACE_DEFINED__
+#define __ICoreWebView2DevToolsProtocolEventReceiver_INTERFACE_DEFINED__
+
+/* interface ICoreWebView2DevToolsProtocolEventReceiver */
+/* [unique][object][uuid] */
+
+
+EXTERN_C __declspec(selectany) const IID IID_ICoreWebView2DevToolsProtocolEventReceiver = {0xb32ca51a,0x8371,0x45e9,{0x93,0x17,0xaf,0x02,0x1d,0x08,0x03,0x67}};
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("b32ca51a-8371-45e9-9317-af021d080367")
+ ICoreWebView2DevToolsProtocolEventReceiver : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE add_DevToolsProtocolEventReceived(
+ /* [in] */ ICoreWebView2DevToolsProtocolEventReceivedEventHandler *handler,
+ /* [out] */ EventRegistrationToken *token) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE remove_DevToolsProtocolEventReceived(
+ /* [in] */ EventRegistrationToken token) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct ICoreWebView2DevToolsProtocolEventReceiverVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ ICoreWebView2DevToolsProtocolEventReceiver * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ ICoreWebView2DevToolsProtocolEventReceiver * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ ICoreWebView2DevToolsProtocolEventReceiver * This);
+
+ HRESULT ( STDMETHODCALLTYPE *add_DevToolsProtocolEventReceived )(
+ ICoreWebView2DevToolsProtocolEventReceiver * This,
+ /* [in] */ ICoreWebView2DevToolsProtocolEventReceivedEventHandler *handler,
+ /* [out] */ EventRegistrationToken *token);
+
+ HRESULT ( STDMETHODCALLTYPE *remove_DevToolsProtocolEventReceived )(
+ ICoreWebView2DevToolsProtocolEventReceiver * This,
+ /* [in] */ EventRegistrationToken token);
+
+ END_INTERFACE
+ } ICoreWebView2DevToolsProtocolEventReceiverVtbl;
+
+ interface ICoreWebView2DevToolsProtocolEventReceiver
+ {
+ CONST_VTBL struct ICoreWebView2DevToolsProtocolEventReceiverVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define ICoreWebView2DevToolsProtocolEventReceiver_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define ICoreWebView2DevToolsProtocolEventReceiver_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define ICoreWebView2DevToolsProtocolEventReceiver_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define ICoreWebView2DevToolsProtocolEventReceiver_add_DevToolsProtocolEventReceived(This,handler,token) \
+ ( (This)->lpVtbl -> add_DevToolsProtocolEventReceived(This,handler,token) )
+
+#define ICoreWebView2DevToolsProtocolEventReceiver_remove_DevToolsProtocolEventReceived(This,token) \
+ ( (This)->lpVtbl -> remove_DevToolsProtocolEventReceived(This,token) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __ICoreWebView2DevToolsProtocolEventReceiver_INTERFACE_DEFINED__ */
+
+
+#ifndef __ICoreWebView2Environment_INTERFACE_DEFINED__
+#define __ICoreWebView2Environment_INTERFACE_DEFINED__
+
+/* interface ICoreWebView2Environment */
+/* [unique][object][uuid] */
+
+
+EXTERN_C __declspec(selectany) const IID IID_ICoreWebView2Environment = {0xb96d755e,0x0319,0x4e92,{0xa2,0x96,0x23,0x43,0x6f,0x46,0xa1,0xfc}};
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("b96d755e-0319-4e92-a296-23436f46a1fc")
+ ICoreWebView2Environment : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE CreateCoreWebView2Controller(
+ HWND parentWindow,
+ ICoreWebView2CreateCoreWebView2ControllerCompletedHandler *handler) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE CreateWebResourceResponse(
+ /* [in] */ IStream *content,
+ /* [in] */ int statusCode,
+ /* [in] */ LPCWSTR reasonPhrase,
+ /* [in] */ LPCWSTR headers,
+ /* [retval][out] */ ICoreWebView2WebResourceResponse **response) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_BrowserVersionString(
+ /* [retval][out] */ LPWSTR *versionInfo) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE add_NewBrowserVersionAvailable(
+ /* [in] */ ICoreWebView2NewBrowserVersionAvailableEventHandler *eventHandler,
+ /* [out] */ EventRegistrationToken *token) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE remove_NewBrowserVersionAvailable(
+ /* [in] */ EventRegistrationToken token) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct ICoreWebView2EnvironmentVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ ICoreWebView2Environment * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ ICoreWebView2Environment * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ ICoreWebView2Environment * This);
+
+ HRESULT ( STDMETHODCALLTYPE *CreateCoreWebView2Controller )(
+ ICoreWebView2Environment * This,
+ HWND parentWindow,
+ ICoreWebView2CreateCoreWebView2ControllerCompletedHandler *handler);
+
+ HRESULT ( STDMETHODCALLTYPE *CreateWebResourceResponse )(
+ ICoreWebView2Environment * This,
+ /* [in] */ IStream *content,
+ /* [in] */ int statusCode,
+ /* [in] */ LPCWSTR reasonPhrase,
+ /* [in] */ LPCWSTR headers,
+ /* [retval][out] */ ICoreWebView2WebResourceResponse **response);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_BrowserVersionString )(
+ ICoreWebView2Environment * This,
+ /* [retval][out] */ LPWSTR *versionInfo);
+
+ HRESULT ( STDMETHODCALLTYPE *add_NewBrowserVersionAvailable )(
+ ICoreWebView2Environment * This,
+ /* [in] */ ICoreWebView2NewBrowserVersionAvailableEventHandler *eventHandler,
+ /* [out] */ EventRegistrationToken *token);
+
+ HRESULT ( STDMETHODCALLTYPE *remove_NewBrowserVersionAvailable )(
+ ICoreWebView2Environment * This,
+ /* [in] */ EventRegistrationToken token);
+
+ END_INTERFACE
+ } ICoreWebView2EnvironmentVtbl;
+
+ interface ICoreWebView2Environment
+ {
+ CONST_VTBL struct ICoreWebView2EnvironmentVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define ICoreWebView2Environment_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define ICoreWebView2Environment_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define ICoreWebView2Environment_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define ICoreWebView2Environment_CreateCoreWebView2Controller(This,parentWindow,handler) \
+ ( (This)->lpVtbl -> CreateCoreWebView2Controller(This,parentWindow,handler) )
+
+#define ICoreWebView2Environment_CreateWebResourceResponse(This,content,statusCode,reasonPhrase,headers,response) \
+ ( (This)->lpVtbl -> CreateWebResourceResponse(This,content,statusCode,reasonPhrase,headers,response) )
+
+#define ICoreWebView2Environment_get_BrowserVersionString(This,versionInfo) \
+ ( (This)->lpVtbl -> get_BrowserVersionString(This,versionInfo) )
+
+#define ICoreWebView2Environment_add_NewBrowserVersionAvailable(This,eventHandler,token) \
+ ( (This)->lpVtbl -> add_NewBrowserVersionAvailable(This,eventHandler,token) )
+
+#define ICoreWebView2Environment_remove_NewBrowserVersionAvailable(This,token) \
+ ( (This)->lpVtbl -> remove_NewBrowserVersionAvailable(This,token) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __ICoreWebView2Environment_INTERFACE_DEFINED__ */
+
+
+#ifndef __ICoreWebView2Environment2_INTERFACE_DEFINED__
+#define __ICoreWebView2Environment2_INTERFACE_DEFINED__
+
+/* interface ICoreWebView2Environment2 */
+/* [unique][object][uuid] */
+
+
+EXTERN_C __declspec(selectany) const IID IID_ICoreWebView2Environment2 = {0x41F3632B,0x5EF4,0x404F,{0xAD,0x82,0x2D,0x60,0x6C,0x5A,0x9A,0x21}};
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("41F3632B-5EF4-404F-AD82-2D606C5A9A21")
+ ICoreWebView2Environment2 : public ICoreWebView2Environment
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE CreateWebResourceRequest(
+ /* [in] */ LPCWSTR uri,
+ /* [in] */ LPCWSTR method,
+ /* [in] */ IStream *postData,
+ /* [in] */ LPCWSTR headers,
+ /* [retval][out] */ ICoreWebView2WebResourceRequest **request) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct ICoreWebView2Environment2Vtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ ICoreWebView2Environment2 * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ ICoreWebView2Environment2 * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ ICoreWebView2Environment2 * This);
+
+ HRESULT ( STDMETHODCALLTYPE *CreateCoreWebView2Controller )(
+ ICoreWebView2Environment2 * This,
+ HWND parentWindow,
+ ICoreWebView2CreateCoreWebView2ControllerCompletedHandler *handler);
+
+ HRESULT ( STDMETHODCALLTYPE *CreateWebResourceResponse )(
+ ICoreWebView2Environment2 * This,
+ /* [in] */ IStream *content,
+ /* [in] */ int statusCode,
+ /* [in] */ LPCWSTR reasonPhrase,
+ /* [in] */ LPCWSTR headers,
+ /* [retval][out] */ ICoreWebView2WebResourceResponse **response);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_BrowserVersionString )(
+ ICoreWebView2Environment2 * This,
+ /* [retval][out] */ LPWSTR *versionInfo);
+
+ HRESULT ( STDMETHODCALLTYPE *add_NewBrowserVersionAvailable )(
+ ICoreWebView2Environment2 * This,
+ /* [in] */ ICoreWebView2NewBrowserVersionAvailableEventHandler *eventHandler,
+ /* [out] */ EventRegistrationToken *token);
+
+ HRESULT ( STDMETHODCALLTYPE *remove_NewBrowserVersionAvailable )(
+ ICoreWebView2Environment2 * This,
+ /* [in] */ EventRegistrationToken token);
+
+ HRESULT ( STDMETHODCALLTYPE *CreateWebResourceRequest )(
+ ICoreWebView2Environment2 * This,
+ /* [in] */ LPCWSTR uri,
+ /* [in] */ LPCWSTR method,
+ /* [in] */ IStream *postData,
+ /* [in] */ LPCWSTR headers,
+ /* [retval][out] */ ICoreWebView2WebResourceRequest **request);
+
+ END_INTERFACE
+ } ICoreWebView2Environment2Vtbl;
+
+ interface ICoreWebView2Environment2
+ {
+ CONST_VTBL struct ICoreWebView2Environment2Vtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define ICoreWebView2Environment2_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define ICoreWebView2Environment2_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define ICoreWebView2Environment2_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define ICoreWebView2Environment2_CreateCoreWebView2Controller(This,parentWindow,handler) \
+ ( (This)->lpVtbl -> CreateCoreWebView2Controller(This,parentWindow,handler) )
+
+#define ICoreWebView2Environment2_CreateWebResourceResponse(This,content,statusCode,reasonPhrase,headers,response) \
+ ( (This)->lpVtbl -> CreateWebResourceResponse(This,content,statusCode,reasonPhrase,headers,response) )
+
+#define ICoreWebView2Environment2_get_BrowserVersionString(This,versionInfo) \
+ ( (This)->lpVtbl -> get_BrowserVersionString(This,versionInfo) )
+
+#define ICoreWebView2Environment2_add_NewBrowserVersionAvailable(This,eventHandler,token) \
+ ( (This)->lpVtbl -> add_NewBrowserVersionAvailable(This,eventHandler,token) )
+
+#define ICoreWebView2Environment2_remove_NewBrowserVersionAvailable(This,token) \
+ ( (This)->lpVtbl -> remove_NewBrowserVersionAvailable(This,token) )
+
+
+#define ICoreWebView2Environment2_CreateWebResourceRequest(This,uri,method,postData,headers,request) \
+ ( (This)->lpVtbl -> CreateWebResourceRequest(This,uri,method,postData,headers,request) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __ICoreWebView2Environment2_INTERFACE_DEFINED__ */
+
+
+#ifndef __ICoreWebView2Environment3_INTERFACE_DEFINED__
+#define __ICoreWebView2Environment3_INTERFACE_DEFINED__
+
+/* interface ICoreWebView2Environment3 */
+/* [unique][object][uuid] */
+
+
+EXTERN_C __declspec(selectany) const IID IID_ICoreWebView2Environment3 = {0x80a22ae3,0xbe7c,0x4ce2,{0xaf,0xe1,0x5a,0x50,0x05,0x6c,0xde,0xeb}};
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("80a22ae3-be7c-4ce2-afe1-5a50056cdeeb")
+ ICoreWebView2Environment3 : public ICoreWebView2Environment2
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE CreateCoreWebView2CompositionController(
+ HWND parentWindow,
+ ICoreWebView2CreateCoreWebView2CompositionControllerCompletedHandler *handler) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE CreateCoreWebView2PointerInfo(
+ /* [retval][out] */ ICoreWebView2PointerInfo **pointerInfo) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct ICoreWebView2Environment3Vtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ ICoreWebView2Environment3 * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ ICoreWebView2Environment3 * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ ICoreWebView2Environment3 * This);
+
+ HRESULT ( STDMETHODCALLTYPE *CreateCoreWebView2Controller )(
+ ICoreWebView2Environment3 * This,
+ HWND parentWindow,
+ ICoreWebView2CreateCoreWebView2ControllerCompletedHandler *handler);
+
+ HRESULT ( STDMETHODCALLTYPE *CreateWebResourceResponse )(
+ ICoreWebView2Environment3 * This,
+ /* [in] */ IStream *content,
+ /* [in] */ int statusCode,
+ /* [in] */ LPCWSTR reasonPhrase,
+ /* [in] */ LPCWSTR headers,
+ /* [retval][out] */ ICoreWebView2WebResourceResponse **response);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_BrowserVersionString )(
+ ICoreWebView2Environment3 * This,
+ /* [retval][out] */ LPWSTR *versionInfo);
+
+ HRESULT ( STDMETHODCALLTYPE *add_NewBrowserVersionAvailable )(
+ ICoreWebView2Environment3 * This,
+ /* [in] */ ICoreWebView2NewBrowserVersionAvailableEventHandler *eventHandler,
+ /* [out] */ EventRegistrationToken *token);
+
+ HRESULT ( STDMETHODCALLTYPE *remove_NewBrowserVersionAvailable )(
+ ICoreWebView2Environment3 * This,
+ /* [in] */ EventRegistrationToken token);
+
+ HRESULT ( STDMETHODCALLTYPE *CreateWebResourceRequest )(
+ ICoreWebView2Environment3 * This,
+ /* [in] */ LPCWSTR uri,
+ /* [in] */ LPCWSTR method,
+ /* [in] */ IStream *postData,
+ /* [in] */ LPCWSTR headers,
+ /* [retval][out] */ ICoreWebView2WebResourceRequest **request);
+
+ HRESULT ( STDMETHODCALLTYPE *CreateCoreWebView2CompositionController )(
+ ICoreWebView2Environment3 * This,
+ HWND parentWindow,
+ ICoreWebView2CreateCoreWebView2CompositionControllerCompletedHandler *handler);
+
+ HRESULT ( STDMETHODCALLTYPE *CreateCoreWebView2PointerInfo )(
+ ICoreWebView2Environment3 * This,
+ /* [retval][out] */ ICoreWebView2PointerInfo **pointerInfo);
+
+ END_INTERFACE
+ } ICoreWebView2Environment3Vtbl;
+
+ interface ICoreWebView2Environment3
+ {
+ CONST_VTBL struct ICoreWebView2Environment3Vtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define ICoreWebView2Environment3_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define ICoreWebView2Environment3_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define ICoreWebView2Environment3_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define ICoreWebView2Environment3_CreateCoreWebView2Controller(This,parentWindow,handler) \
+ ( (This)->lpVtbl -> CreateCoreWebView2Controller(This,parentWindow,handler) )
+
+#define ICoreWebView2Environment3_CreateWebResourceResponse(This,content,statusCode,reasonPhrase,headers,response) \
+ ( (This)->lpVtbl -> CreateWebResourceResponse(This,content,statusCode,reasonPhrase,headers,response) )
+
+#define ICoreWebView2Environment3_get_BrowserVersionString(This,versionInfo) \
+ ( (This)->lpVtbl -> get_BrowserVersionString(This,versionInfo) )
+
+#define ICoreWebView2Environment3_add_NewBrowserVersionAvailable(This,eventHandler,token) \
+ ( (This)->lpVtbl -> add_NewBrowserVersionAvailable(This,eventHandler,token) )
+
+#define ICoreWebView2Environment3_remove_NewBrowserVersionAvailable(This,token) \
+ ( (This)->lpVtbl -> remove_NewBrowserVersionAvailable(This,token) )
+
+
+#define ICoreWebView2Environment3_CreateWebResourceRequest(This,uri,method,postData,headers,request) \
+ ( (This)->lpVtbl -> CreateWebResourceRequest(This,uri,method,postData,headers,request) )
+
+
+#define ICoreWebView2Environment3_CreateCoreWebView2CompositionController(This,parentWindow,handler) \
+ ( (This)->lpVtbl -> CreateCoreWebView2CompositionController(This,parentWindow,handler) )
+
+#define ICoreWebView2Environment3_CreateCoreWebView2PointerInfo(This,pointerInfo) \
+ ( (This)->lpVtbl -> CreateCoreWebView2PointerInfo(This,pointerInfo) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __ICoreWebView2Environment3_INTERFACE_DEFINED__ */
+
+
+#ifndef __ICoreWebView2Environment4_INTERFACE_DEFINED__
+#define __ICoreWebView2Environment4_INTERFACE_DEFINED__
+
+/* interface ICoreWebView2Environment4 */
+/* [unique][object][uuid] */
+
+
+EXTERN_C __declspec(selectany) const IID IID_ICoreWebView2Environment4 = {0x20944379,0x6dcf,0x41d6,{0xa0,0xa0,0xab,0xc0,0xfc,0x50,0xde,0x0d}};
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("20944379-6dcf-41d6-a0a0-abc0fc50de0d")
+ ICoreWebView2Environment4 : public ICoreWebView2Environment3
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE GetProviderForHwnd(
+ /* [in] */ HWND hwnd,
+ /* [retval][out] */ IUnknown **provider) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct ICoreWebView2Environment4Vtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ ICoreWebView2Environment4 * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ ICoreWebView2Environment4 * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ ICoreWebView2Environment4 * This);
+
+ HRESULT ( STDMETHODCALLTYPE *CreateCoreWebView2Controller )(
+ ICoreWebView2Environment4 * This,
+ HWND parentWindow,
+ ICoreWebView2CreateCoreWebView2ControllerCompletedHandler *handler);
+
+ HRESULT ( STDMETHODCALLTYPE *CreateWebResourceResponse )(
+ ICoreWebView2Environment4 * This,
+ /* [in] */ IStream *content,
+ /* [in] */ int statusCode,
+ /* [in] */ LPCWSTR reasonPhrase,
+ /* [in] */ LPCWSTR headers,
+ /* [retval][out] */ ICoreWebView2WebResourceResponse **response);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_BrowserVersionString )(
+ ICoreWebView2Environment4 * This,
+ /* [retval][out] */ LPWSTR *versionInfo);
+
+ HRESULT ( STDMETHODCALLTYPE *add_NewBrowserVersionAvailable )(
+ ICoreWebView2Environment4 * This,
+ /* [in] */ ICoreWebView2NewBrowserVersionAvailableEventHandler *eventHandler,
+ /* [out] */ EventRegistrationToken *token);
+
+ HRESULT ( STDMETHODCALLTYPE *remove_NewBrowserVersionAvailable )(
+ ICoreWebView2Environment4 * This,
+ /* [in] */ EventRegistrationToken token);
+
+ HRESULT ( STDMETHODCALLTYPE *CreateWebResourceRequest )(
+ ICoreWebView2Environment4 * This,
+ /* [in] */ LPCWSTR uri,
+ /* [in] */ LPCWSTR method,
+ /* [in] */ IStream *postData,
+ /* [in] */ LPCWSTR headers,
+ /* [retval][out] */ ICoreWebView2WebResourceRequest **request);
+
+ HRESULT ( STDMETHODCALLTYPE *CreateCoreWebView2CompositionController )(
+ ICoreWebView2Environment4 * This,
+ HWND parentWindow,
+ ICoreWebView2CreateCoreWebView2CompositionControllerCompletedHandler *handler);
+
+ HRESULT ( STDMETHODCALLTYPE *CreateCoreWebView2PointerInfo )(
+ ICoreWebView2Environment4 * This,
+ /* [retval][out] */ ICoreWebView2PointerInfo **pointerInfo);
+
+ HRESULT ( STDMETHODCALLTYPE *GetProviderForHwnd )(
+ ICoreWebView2Environment4 * This,
+ /* [in] */ HWND hwnd,
+ /* [retval][out] */ IUnknown **provider);
+
+ END_INTERFACE
+ } ICoreWebView2Environment4Vtbl;
+
+ interface ICoreWebView2Environment4
+ {
+ CONST_VTBL struct ICoreWebView2Environment4Vtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define ICoreWebView2Environment4_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define ICoreWebView2Environment4_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define ICoreWebView2Environment4_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define ICoreWebView2Environment4_CreateCoreWebView2Controller(This,parentWindow,handler) \
+ ( (This)->lpVtbl -> CreateCoreWebView2Controller(This,parentWindow,handler) )
+
+#define ICoreWebView2Environment4_CreateWebResourceResponse(This,content,statusCode,reasonPhrase,headers,response) \
+ ( (This)->lpVtbl -> CreateWebResourceResponse(This,content,statusCode,reasonPhrase,headers,response) )
+
+#define ICoreWebView2Environment4_get_BrowserVersionString(This,versionInfo) \
+ ( (This)->lpVtbl -> get_BrowserVersionString(This,versionInfo) )
+
+#define ICoreWebView2Environment4_add_NewBrowserVersionAvailable(This,eventHandler,token) \
+ ( (This)->lpVtbl -> add_NewBrowserVersionAvailable(This,eventHandler,token) )
+
+#define ICoreWebView2Environment4_remove_NewBrowserVersionAvailable(This,token) \
+ ( (This)->lpVtbl -> remove_NewBrowserVersionAvailable(This,token) )
+
+
+#define ICoreWebView2Environment4_CreateWebResourceRequest(This,uri,method,postData,headers,request) \
+ ( (This)->lpVtbl -> CreateWebResourceRequest(This,uri,method,postData,headers,request) )
+
+
+#define ICoreWebView2Environment4_CreateCoreWebView2CompositionController(This,parentWindow,handler) \
+ ( (This)->lpVtbl -> CreateCoreWebView2CompositionController(This,parentWindow,handler) )
+
+#define ICoreWebView2Environment4_CreateCoreWebView2PointerInfo(This,pointerInfo) \
+ ( (This)->lpVtbl -> CreateCoreWebView2PointerInfo(This,pointerInfo) )
+
+
+#define ICoreWebView2Environment4_GetProviderForHwnd(This,hwnd,provider) \
+ ( (This)->lpVtbl -> GetProviderForHwnd(This,hwnd,provider) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __ICoreWebView2Environment4_INTERFACE_DEFINED__ */
+
+
+#ifndef __ICoreWebView2EnvironmentOptions_INTERFACE_DEFINED__
+#define __ICoreWebView2EnvironmentOptions_INTERFACE_DEFINED__
+
+/* interface ICoreWebView2EnvironmentOptions */
+/* [unique][object][uuid] */
+
+
+EXTERN_C __declspec(selectany) const IID IID_ICoreWebView2EnvironmentOptions = {0x2fde08a8,0x1e9a,0x4766,{0x8c,0x05,0x95,0xa9,0xce,0xb9,0xd1,0xc5}};
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("2fde08a8-1e9a-4766-8c05-95a9ceb9d1c5")
+ ICoreWebView2EnvironmentOptions : public IUnknown
+ {
+ public:
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_AdditionalBrowserArguments(
+ /* [retval][out] */ LPWSTR *value) = 0;
+
+ virtual /* [propput] */ HRESULT STDMETHODCALLTYPE put_AdditionalBrowserArguments(
+ /* [in] */ LPCWSTR value) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_Language(
+ /* [retval][out] */ LPWSTR *value) = 0;
+
+ virtual /* [propput] */ HRESULT STDMETHODCALLTYPE put_Language(
+ /* [in] */ LPCWSTR value) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_TargetCompatibleBrowserVersion(
+ /* [retval][out] */ LPWSTR *value) = 0;
+
+ virtual /* [propput] */ HRESULT STDMETHODCALLTYPE put_TargetCompatibleBrowserVersion(
+ /* [in] */ LPCWSTR value) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_AllowSingleSignOnUsingOSPrimaryAccount(
+ /* [retval][out] */ BOOL *allow) = 0;
+
+ virtual /* [propput] */ HRESULT STDMETHODCALLTYPE put_AllowSingleSignOnUsingOSPrimaryAccount(
+ /* [in] */ BOOL allow) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct ICoreWebView2EnvironmentOptionsVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ ICoreWebView2EnvironmentOptions * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ ICoreWebView2EnvironmentOptions * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ ICoreWebView2EnvironmentOptions * This);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_AdditionalBrowserArguments )(
+ ICoreWebView2EnvironmentOptions * This,
+ /* [retval][out] */ LPWSTR *value);
+
+ /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_AdditionalBrowserArguments )(
+ ICoreWebView2EnvironmentOptions * This,
+ /* [in] */ LPCWSTR value);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_Language )(
+ ICoreWebView2EnvironmentOptions * This,
+ /* [retval][out] */ LPWSTR *value);
+
+ /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_Language )(
+ ICoreWebView2EnvironmentOptions * This,
+ /* [in] */ LPCWSTR value);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_TargetCompatibleBrowserVersion )(
+ ICoreWebView2EnvironmentOptions * This,
+ /* [retval][out] */ LPWSTR *value);
+
+ /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_TargetCompatibleBrowserVersion )(
+ ICoreWebView2EnvironmentOptions * This,
+ /* [in] */ LPCWSTR value);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_AllowSingleSignOnUsingOSPrimaryAccount )(
+ ICoreWebView2EnvironmentOptions * This,
+ /* [retval][out] */ BOOL *allow);
+
+ /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_AllowSingleSignOnUsingOSPrimaryAccount )(
+ ICoreWebView2EnvironmentOptions * This,
+ /* [in] */ BOOL allow);
+
+ END_INTERFACE
+ } ICoreWebView2EnvironmentOptionsVtbl;
+
+ interface ICoreWebView2EnvironmentOptions
+ {
+ CONST_VTBL struct ICoreWebView2EnvironmentOptionsVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define ICoreWebView2EnvironmentOptions_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define ICoreWebView2EnvironmentOptions_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define ICoreWebView2EnvironmentOptions_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define ICoreWebView2EnvironmentOptions_get_AdditionalBrowserArguments(This,value) \
+ ( (This)->lpVtbl -> get_AdditionalBrowserArguments(This,value) )
+
+#define ICoreWebView2EnvironmentOptions_put_AdditionalBrowserArguments(This,value) \
+ ( (This)->lpVtbl -> put_AdditionalBrowserArguments(This,value) )
+
+#define ICoreWebView2EnvironmentOptions_get_Language(This,value) \
+ ( (This)->lpVtbl -> get_Language(This,value) )
+
+#define ICoreWebView2EnvironmentOptions_put_Language(This,value) \
+ ( (This)->lpVtbl -> put_Language(This,value) )
+
+#define ICoreWebView2EnvironmentOptions_get_TargetCompatibleBrowserVersion(This,value) \
+ ( (This)->lpVtbl -> get_TargetCompatibleBrowserVersion(This,value) )
+
+#define ICoreWebView2EnvironmentOptions_put_TargetCompatibleBrowserVersion(This,value) \
+ ( (This)->lpVtbl -> put_TargetCompatibleBrowserVersion(This,value) )
+
+#define ICoreWebView2EnvironmentOptions_get_AllowSingleSignOnUsingOSPrimaryAccount(This,allow) \
+ ( (This)->lpVtbl -> get_AllowSingleSignOnUsingOSPrimaryAccount(This,allow) )
+
+#define ICoreWebView2EnvironmentOptions_put_AllowSingleSignOnUsingOSPrimaryAccount(This,allow) \
+ ( (This)->lpVtbl -> put_AllowSingleSignOnUsingOSPrimaryAccount(This,allow) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __ICoreWebView2EnvironmentOptions_INTERFACE_DEFINED__ */
+
+
+#ifndef __ICoreWebView2ExecuteScriptCompletedHandler_INTERFACE_DEFINED__
+#define __ICoreWebView2ExecuteScriptCompletedHandler_INTERFACE_DEFINED__
+
+/* interface ICoreWebView2ExecuteScriptCompletedHandler */
+/* [unique][object][uuid] */
+
+
+EXTERN_C __declspec(selectany) const IID IID_ICoreWebView2ExecuteScriptCompletedHandler = {0x49511172,0xcc67,0x4bca,{0x99,0x23,0x13,0x71,0x12,0xf4,0xc4,0xcc}};
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("49511172-cc67-4bca-9923-137112f4c4cc")
+ ICoreWebView2ExecuteScriptCompletedHandler : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE Invoke(
+ /* [in] */ HRESULT errorCode,
+ /* [in] */ LPCWSTR resultObjectAsJson) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct ICoreWebView2ExecuteScriptCompletedHandlerVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ ICoreWebView2ExecuteScriptCompletedHandler * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ ICoreWebView2ExecuteScriptCompletedHandler * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ ICoreWebView2ExecuteScriptCompletedHandler * This);
+
+ HRESULT ( STDMETHODCALLTYPE *Invoke )(
+ ICoreWebView2ExecuteScriptCompletedHandler * This,
+ /* [in] */ HRESULT errorCode,
+ /* [in] */ LPCWSTR resultObjectAsJson);
+
+ END_INTERFACE
+ } ICoreWebView2ExecuteScriptCompletedHandlerVtbl;
+
+ interface ICoreWebView2ExecuteScriptCompletedHandler
+ {
+ CONST_VTBL struct ICoreWebView2ExecuteScriptCompletedHandlerVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define ICoreWebView2ExecuteScriptCompletedHandler_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define ICoreWebView2ExecuteScriptCompletedHandler_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define ICoreWebView2ExecuteScriptCompletedHandler_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define ICoreWebView2ExecuteScriptCompletedHandler_Invoke(This,errorCode,resultObjectAsJson) \
+ ( (This)->lpVtbl -> Invoke(This,errorCode,resultObjectAsJson) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __ICoreWebView2ExecuteScriptCompletedHandler_INTERFACE_DEFINED__ */
+
+
+#ifndef __ICoreWebView2FrameInfo_INTERFACE_DEFINED__
+#define __ICoreWebView2FrameInfo_INTERFACE_DEFINED__
+
+/* interface ICoreWebView2FrameInfo */
+/* [unique][object][uuid] */
+
+
+EXTERN_C __declspec(selectany) const IID IID_ICoreWebView2FrameInfo = {0xda86b8a1,0xbdf3,0x4f11,{0x99,0x55,0x52,0x8c,0xef,0xa5,0x97,0x27}};
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("da86b8a1-bdf3-4f11-9955-528cefa59727")
+ ICoreWebView2FrameInfo : public IUnknown
+ {
+ public:
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_Name(
+ /* [retval][out] */ LPWSTR *name) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_Source(
+ /* [retval][out] */ LPWSTR *source) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct ICoreWebView2FrameInfoVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ ICoreWebView2FrameInfo * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ ICoreWebView2FrameInfo * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ ICoreWebView2FrameInfo * This);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_Name )(
+ ICoreWebView2FrameInfo * This,
+ /* [retval][out] */ LPWSTR *name);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_Source )(
+ ICoreWebView2FrameInfo * This,
+ /* [retval][out] */ LPWSTR *source);
+
+ END_INTERFACE
+ } ICoreWebView2FrameInfoVtbl;
+
+ interface ICoreWebView2FrameInfo
+ {
+ CONST_VTBL struct ICoreWebView2FrameInfoVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define ICoreWebView2FrameInfo_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define ICoreWebView2FrameInfo_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define ICoreWebView2FrameInfo_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define ICoreWebView2FrameInfo_get_Name(This,name) \
+ ( (This)->lpVtbl -> get_Name(This,name) )
+
+#define ICoreWebView2FrameInfo_get_Source(This,source) \
+ ( (This)->lpVtbl -> get_Source(This,source) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __ICoreWebView2FrameInfo_INTERFACE_DEFINED__ */
+
+
+#ifndef __ICoreWebView2FrameInfoCollection_INTERFACE_DEFINED__
+#define __ICoreWebView2FrameInfoCollection_INTERFACE_DEFINED__
+
+/* interface ICoreWebView2FrameInfoCollection */
+/* [unique][object][uuid] */
+
+
+EXTERN_C __declspec(selectany) const IID IID_ICoreWebView2FrameInfoCollection = {0x8f834154,0xd38e,0x4d90,{0xaf,0xfb,0x68,0x00,0xa7,0x27,0x28,0x39}};
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("8f834154-d38e-4d90-affb-6800a7272839")
+ ICoreWebView2FrameInfoCollection : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE GetIterator(
+ /* [retval][out] */ ICoreWebView2FrameInfoCollectionIterator **iterator) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct ICoreWebView2FrameInfoCollectionVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ ICoreWebView2FrameInfoCollection * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ ICoreWebView2FrameInfoCollection * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ ICoreWebView2FrameInfoCollection * This);
+
+ HRESULT ( STDMETHODCALLTYPE *GetIterator )(
+ ICoreWebView2FrameInfoCollection * This,
+ /* [retval][out] */ ICoreWebView2FrameInfoCollectionIterator **iterator);
+
+ END_INTERFACE
+ } ICoreWebView2FrameInfoCollectionVtbl;
+
+ interface ICoreWebView2FrameInfoCollection
+ {
+ CONST_VTBL struct ICoreWebView2FrameInfoCollectionVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define ICoreWebView2FrameInfoCollection_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define ICoreWebView2FrameInfoCollection_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define ICoreWebView2FrameInfoCollection_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define ICoreWebView2FrameInfoCollection_GetIterator(This,iterator) \
+ ( (This)->lpVtbl -> GetIterator(This,iterator) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __ICoreWebView2FrameInfoCollection_INTERFACE_DEFINED__ */
+
+
+#ifndef __ICoreWebView2FrameInfoCollectionIterator_INTERFACE_DEFINED__
+#define __ICoreWebView2FrameInfoCollectionIterator_INTERFACE_DEFINED__
+
+/* interface ICoreWebView2FrameInfoCollectionIterator */
+/* [unique][object][uuid] */
+
+
+EXTERN_C __declspec(selectany) const IID IID_ICoreWebView2FrameInfoCollectionIterator = {0x1bf89e2d,0x1b2b,0x4629,{0xb2,0x8f,0x05,0x09,0x9b,0x41,0xbb,0x03}};
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("1bf89e2d-1b2b-4629-b28f-05099b41bb03")
+ ICoreWebView2FrameInfoCollectionIterator : public IUnknown
+ {
+ public:
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_HasCurrent(
+ /* [retval][out] */ BOOL *hasCurrent) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetCurrent(
+ /* [retval][out] */ ICoreWebView2FrameInfo **frameInfo) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE MoveNext(
+ /* [retval][out] */ BOOL *hasNext) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct ICoreWebView2FrameInfoCollectionIteratorVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ ICoreWebView2FrameInfoCollectionIterator * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ ICoreWebView2FrameInfoCollectionIterator * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ ICoreWebView2FrameInfoCollectionIterator * This);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_HasCurrent )(
+ ICoreWebView2FrameInfoCollectionIterator * This,
+ /* [retval][out] */ BOOL *hasCurrent);
+
+ HRESULT ( STDMETHODCALLTYPE *GetCurrent )(
+ ICoreWebView2FrameInfoCollectionIterator * This,
+ /* [retval][out] */ ICoreWebView2FrameInfo **frameInfo);
+
+ HRESULT ( STDMETHODCALLTYPE *MoveNext )(
+ ICoreWebView2FrameInfoCollectionIterator * This,
+ /* [retval][out] */ BOOL *hasNext);
+
+ END_INTERFACE
+ } ICoreWebView2FrameInfoCollectionIteratorVtbl;
+
+ interface ICoreWebView2FrameInfoCollectionIterator
+ {
+ CONST_VTBL struct ICoreWebView2FrameInfoCollectionIteratorVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define ICoreWebView2FrameInfoCollectionIterator_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define ICoreWebView2FrameInfoCollectionIterator_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define ICoreWebView2FrameInfoCollectionIterator_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define ICoreWebView2FrameInfoCollectionIterator_get_HasCurrent(This,hasCurrent) \
+ ( (This)->lpVtbl -> get_HasCurrent(This,hasCurrent) )
+
+#define ICoreWebView2FrameInfoCollectionIterator_GetCurrent(This,frameInfo) \
+ ( (This)->lpVtbl -> GetCurrent(This,frameInfo) )
+
+#define ICoreWebView2FrameInfoCollectionIterator_MoveNext(This,hasNext) \
+ ( (This)->lpVtbl -> MoveNext(This,hasNext) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __ICoreWebView2FrameInfoCollectionIterator_INTERFACE_DEFINED__ */
+
+
+#ifndef __ICoreWebView2FocusChangedEventHandler_INTERFACE_DEFINED__
+#define __ICoreWebView2FocusChangedEventHandler_INTERFACE_DEFINED__
+
+/* interface ICoreWebView2FocusChangedEventHandler */
+/* [unique][object][uuid] */
+
+
+EXTERN_C __declspec(selectany) const IID IID_ICoreWebView2FocusChangedEventHandler = {0x05ea24bd,0x6452,0x4926,{0x90,0x14,0x4b,0x82,0xb4,0x98,0x13,0x5d}};
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("05ea24bd-6452-4926-9014-4b82b498135d")
+ ICoreWebView2FocusChangedEventHandler : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE Invoke(
+ /* [in] */ ICoreWebView2Controller *sender,
+ /* [in] */ IUnknown *args) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct ICoreWebView2FocusChangedEventHandlerVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ ICoreWebView2FocusChangedEventHandler * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ ICoreWebView2FocusChangedEventHandler * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ ICoreWebView2FocusChangedEventHandler * This);
+
+ HRESULT ( STDMETHODCALLTYPE *Invoke )(
+ ICoreWebView2FocusChangedEventHandler * This,
+ /* [in] */ ICoreWebView2Controller *sender,
+ /* [in] */ IUnknown *args);
+
+ END_INTERFACE
+ } ICoreWebView2FocusChangedEventHandlerVtbl;
+
+ interface ICoreWebView2FocusChangedEventHandler
+ {
+ CONST_VTBL struct ICoreWebView2FocusChangedEventHandlerVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define ICoreWebView2FocusChangedEventHandler_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define ICoreWebView2FocusChangedEventHandler_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define ICoreWebView2FocusChangedEventHandler_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define ICoreWebView2FocusChangedEventHandler_Invoke(This,sender,args) \
+ ( (This)->lpVtbl -> Invoke(This,sender,args) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __ICoreWebView2FocusChangedEventHandler_INTERFACE_DEFINED__ */
+
+
+#ifndef __ICoreWebView2GetCookiesCompletedHandler_INTERFACE_DEFINED__
+#define __ICoreWebView2GetCookiesCompletedHandler_INTERFACE_DEFINED__
+
+/* interface ICoreWebView2GetCookiesCompletedHandler */
+/* [unique][object][uuid] */
+
+
+EXTERN_C __declspec(selectany) const IID IID_ICoreWebView2GetCookiesCompletedHandler = {0x5A4F5069,0x5C15,0x47C3,{0x86,0x46,0xF4,0xDE,0x1C,0x11,0x66,0x70}};
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("5A4F5069-5C15-47C3-8646-F4DE1C116670")
+ ICoreWebView2GetCookiesCompletedHandler : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE Invoke(
+ HRESULT result,
+ ICoreWebView2CookieList *cookieList) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct ICoreWebView2GetCookiesCompletedHandlerVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ ICoreWebView2GetCookiesCompletedHandler * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ ICoreWebView2GetCookiesCompletedHandler * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ ICoreWebView2GetCookiesCompletedHandler * This);
+
+ HRESULT ( STDMETHODCALLTYPE *Invoke )(
+ ICoreWebView2GetCookiesCompletedHandler * This,
+ HRESULT result,
+ ICoreWebView2CookieList *cookieList);
+
+ END_INTERFACE
+ } ICoreWebView2GetCookiesCompletedHandlerVtbl;
+
+ interface ICoreWebView2GetCookiesCompletedHandler
+ {
+ CONST_VTBL struct ICoreWebView2GetCookiesCompletedHandlerVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define ICoreWebView2GetCookiesCompletedHandler_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define ICoreWebView2GetCookiesCompletedHandler_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define ICoreWebView2GetCookiesCompletedHandler_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define ICoreWebView2GetCookiesCompletedHandler_Invoke(This,result,cookieList) \
+ ( (This)->lpVtbl -> Invoke(This,result,cookieList) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __ICoreWebView2GetCookiesCompletedHandler_INTERFACE_DEFINED__ */
+
+
+#ifndef __ICoreWebView2HistoryChangedEventHandler_INTERFACE_DEFINED__
+#define __ICoreWebView2HistoryChangedEventHandler_INTERFACE_DEFINED__
+
+/* interface ICoreWebView2HistoryChangedEventHandler */
+/* [unique][object][uuid] */
+
+
+EXTERN_C __declspec(selectany) const IID IID_ICoreWebView2HistoryChangedEventHandler = {0xc79a420c,0xefd9,0x4058,{0x92,0x95,0x3e,0x8b,0x4b,0xca,0xb6,0x45}};
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("c79a420c-efd9-4058-9295-3e8b4bcab645")
+ ICoreWebView2HistoryChangedEventHandler : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE Invoke(
+ /* [in] */ ICoreWebView2 *sender,
+ /* [in] */ IUnknown *args) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct ICoreWebView2HistoryChangedEventHandlerVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ ICoreWebView2HistoryChangedEventHandler * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ ICoreWebView2HistoryChangedEventHandler * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ ICoreWebView2HistoryChangedEventHandler * This);
+
+ HRESULT ( STDMETHODCALLTYPE *Invoke )(
+ ICoreWebView2HistoryChangedEventHandler * This,
+ /* [in] */ ICoreWebView2 *sender,
+ /* [in] */ IUnknown *args);
+
+ END_INTERFACE
+ } ICoreWebView2HistoryChangedEventHandlerVtbl;
+
+ interface ICoreWebView2HistoryChangedEventHandler
+ {
+ CONST_VTBL struct ICoreWebView2HistoryChangedEventHandlerVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define ICoreWebView2HistoryChangedEventHandler_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define ICoreWebView2HistoryChangedEventHandler_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define ICoreWebView2HistoryChangedEventHandler_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define ICoreWebView2HistoryChangedEventHandler_Invoke(This,sender,args) \
+ ( (This)->lpVtbl -> Invoke(This,sender,args) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __ICoreWebView2HistoryChangedEventHandler_INTERFACE_DEFINED__ */
+
+
+#ifndef __ICoreWebView2HttpHeadersCollectionIterator_INTERFACE_DEFINED__
+#define __ICoreWebView2HttpHeadersCollectionIterator_INTERFACE_DEFINED__
+
+/* interface ICoreWebView2HttpHeadersCollectionIterator */
+/* [unique][object][uuid] */
+
+
+EXTERN_C __declspec(selectany) const IID IID_ICoreWebView2HttpHeadersCollectionIterator = {0x0702fc30,0xf43b,0x47bb,{0xab,0x52,0xa4,0x2c,0xb5,0x52,0xad,0x9f}};
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("0702fc30-f43b-47bb-ab52-a42cb552ad9f")
+ ICoreWebView2HttpHeadersCollectionIterator : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE GetCurrentHeader(
+ /* [out] */ LPWSTR *name,
+ /* [out] */ LPWSTR *value) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_HasCurrentHeader(
+ /* [retval][out] */ BOOL *hasCurrent) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE MoveNext(
+ /* [retval][out] */ BOOL *hasNext) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct ICoreWebView2HttpHeadersCollectionIteratorVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ ICoreWebView2HttpHeadersCollectionIterator * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ ICoreWebView2HttpHeadersCollectionIterator * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ ICoreWebView2HttpHeadersCollectionIterator * This);
+
+ HRESULT ( STDMETHODCALLTYPE *GetCurrentHeader )(
+ ICoreWebView2HttpHeadersCollectionIterator * This,
+ /* [out] */ LPWSTR *name,
+ /* [out] */ LPWSTR *value);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_HasCurrentHeader )(
+ ICoreWebView2HttpHeadersCollectionIterator * This,
+ /* [retval][out] */ BOOL *hasCurrent);
+
+ HRESULT ( STDMETHODCALLTYPE *MoveNext )(
+ ICoreWebView2HttpHeadersCollectionIterator * This,
+ /* [retval][out] */ BOOL *hasNext);
+
+ END_INTERFACE
+ } ICoreWebView2HttpHeadersCollectionIteratorVtbl;
+
+ interface ICoreWebView2HttpHeadersCollectionIterator
+ {
+ CONST_VTBL struct ICoreWebView2HttpHeadersCollectionIteratorVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define ICoreWebView2HttpHeadersCollectionIterator_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define ICoreWebView2HttpHeadersCollectionIterator_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define ICoreWebView2HttpHeadersCollectionIterator_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define ICoreWebView2HttpHeadersCollectionIterator_GetCurrentHeader(This,name,value) \
+ ( (This)->lpVtbl -> GetCurrentHeader(This,name,value) )
+
+#define ICoreWebView2HttpHeadersCollectionIterator_get_HasCurrentHeader(This,hasCurrent) \
+ ( (This)->lpVtbl -> get_HasCurrentHeader(This,hasCurrent) )
+
+#define ICoreWebView2HttpHeadersCollectionIterator_MoveNext(This,hasNext) \
+ ( (This)->lpVtbl -> MoveNext(This,hasNext) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __ICoreWebView2HttpHeadersCollectionIterator_INTERFACE_DEFINED__ */
+
+
+#ifndef __ICoreWebView2HttpRequestHeaders_INTERFACE_DEFINED__
+#define __ICoreWebView2HttpRequestHeaders_INTERFACE_DEFINED__
+
+/* interface ICoreWebView2HttpRequestHeaders */
+/* [unique][object][uuid] */
+
+
+EXTERN_C __declspec(selectany) const IID IID_ICoreWebView2HttpRequestHeaders = {0xe86cac0e,0x5523,0x465c,{0xb5,0x36,0x8f,0xb9,0xfc,0x8c,0x8c,0x60}};
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("e86cac0e-5523-465c-b536-8fb9fc8c8c60")
+ ICoreWebView2HttpRequestHeaders : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE GetHeader(
+ /* [in] */ LPCWSTR name,
+ /* [retval][out] */ LPWSTR *value) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetHeaders(
+ /* [in] */ LPCWSTR name,
+ /* [retval][out] */ ICoreWebView2HttpHeadersCollectionIterator **iterator) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE Contains(
+ /* [in] */ LPCWSTR name,
+ /* [retval][out] */ BOOL *contains) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SetHeader(
+ /* [in] */ LPCWSTR name,
+ /* [in] */ LPCWSTR value) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE RemoveHeader(
+ /* [in] */ LPCWSTR name) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetIterator(
+ /* [retval][out] */ ICoreWebView2HttpHeadersCollectionIterator **iterator) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct ICoreWebView2HttpRequestHeadersVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ ICoreWebView2HttpRequestHeaders * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ ICoreWebView2HttpRequestHeaders * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ ICoreWebView2HttpRequestHeaders * This);
+
+ HRESULT ( STDMETHODCALLTYPE *GetHeader )(
+ ICoreWebView2HttpRequestHeaders * This,
+ /* [in] */ LPCWSTR name,
+ /* [retval][out] */ LPWSTR *value);
+
+ HRESULT ( STDMETHODCALLTYPE *GetHeaders )(
+ ICoreWebView2HttpRequestHeaders * This,
+ /* [in] */ LPCWSTR name,
+ /* [retval][out] */ ICoreWebView2HttpHeadersCollectionIterator **iterator);
+
+ HRESULT ( STDMETHODCALLTYPE *Contains )(
+ ICoreWebView2HttpRequestHeaders * This,
+ /* [in] */ LPCWSTR name,
+ /* [retval][out] */ BOOL *contains);
+
+ HRESULT ( STDMETHODCALLTYPE *SetHeader )(
+ ICoreWebView2HttpRequestHeaders * This,
+ /* [in] */ LPCWSTR name,
+ /* [in] */ LPCWSTR value);
+
+ HRESULT ( STDMETHODCALLTYPE *RemoveHeader )(
+ ICoreWebView2HttpRequestHeaders * This,
+ /* [in] */ LPCWSTR name);
+
+ HRESULT ( STDMETHODCALLTYPE *GetIterator )(
+ ICoreWebView2HttpRequestHeaders * This,
+ /* [retval][out] */ ICoreWebView2HttpHeadersCollectionIterator **iterator);
+
+ END_INTERFACE
+ } ICoreWebView2HttpRequestHeadersVtbl;
+
+ interface ICoreWebView2HttpRequestHeaders
+ {
+ CONST_VTBL struct ICoreWebView2HttpRequestHeadersVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define ICoreWebView2HttpRequestHeaders_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define ICoreWebView2HttpRequestHeaders_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define ICoreWebView2HttpRequestHeaders_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define ICoreWebView2HttpRequestHeaders_GetHeader(This,name,value) \
+ ( (This)->lpVtbl -> GetHeader(This,name,value) )
+
+#define ICoreWebView2HttpRequestHeaders_GetHeaders(This,name,iterator) \
+ ( (This)->lpVtbl -> GetHeaders(This,name,iterator) )
+
+#define ICoreWebView2HttpRequestHeaders_Contains(This,name,contains) \
+ ( (This)->lpVtbl -> Contains(This,name,contains) )
+
+#define ICoreWebView2HttpRequestHeaders_SetHeader(This,name,value) \
+ ( (This)->lpVtbl -> SetHeader(This,name,value) )
+
+#define ICoreWebView2HttpRequestHeaders_RemoveHeader(This,name) \
+ ( (This)->lpVtbl -> RemoveHeader(This,name) )
+
+#define ICoreWebView2HttpRequestHeaders_GetIterator(This,iterator) \
+ ( (This)->lpVtbl -> GetIterator(This,iterator) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __ICoreWebView2HttpRequestHeaders_INTERFACE_DEFINED__ */
+
+
+#ifndef __ICoreWebView2HttpResponseHeaders_INTERFACE_DEFINED__
+#define __ICoreWebView2HttpResponseHeaders_INTERFACE_DEFINED__
+
+/* interface ICoreWebView2HttpResponseHeaders */
+/* [unique][object][uuid] */
+
+
+EXTERN_C __declspec(selectany) const IID IID_ICoreWebView2HttpResponseHeaders = {0x03c5ff5a,0x9b45,0x4a88,{0x88,0x1c,0x89,0xa9,0xf3,0x28,0x61,0x9c}};
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("03c5ff5a-9b45-4a88-881c-89a9f328619c")
+ ICoreWebView2HttpResponseHeaders : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE AppendHeader(
+ /* [in] */ LPCWSTR name,
+ /* [in] */ LPCWSTR value) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE Contains(
+ /* [in] */ LPCWSTR name,
+ /* [retval][out] */ BOOL *contains) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetHeader(
+ /* [in] */ LPCWSTR name,
+ /* [retval][out] */ LPWSTR *value) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetHeaders(
+ /* [in] */ LPCWSTR name,
+ /* [retval][out] */ ICoreWebView2HttpHeadersCollectionIterator **iterator) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetIterator(
+ /* [retval][out] */ ICoreWebView2HttpHeadersCollectionIterator **iterator) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct ICoreWebView2HttpResponseHeadersVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ ICoreWebView2HttpResponseHeaders * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ ICoreWebView2HttpResponseHeaders * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ ICoreWebView2HttpResponseHeaders * This);
+
+ HRESULT ( STDMETHODCALLTYPE *AppendHeader )(
+ ICoreWebView2HttpResponseHeaders * This,
+ /* [in] */ LPCWSTR name,
+ /* [in] */ LPCWSTR value);
+
+ HRESULT ( STDMETHODCALLTYPE *Contains )(
+ ICoreWebView2HttpResponseHeaders * This,
+ /* [in] */ LPCWSTR name,
+ /* [retval][out] */ BOOL *contains);
+
+ HRESULT ( STDMETHODCALLTYPE *GetHeader )(
+ ICoreWebView2HttpResponseHeaders * This,
+ /* [in] */ LPCWSTR name,
+ /* [retval][out] */ LPWSTR *value);
+
+ HRESULT ( STDMETHODCALLTYPE *GetHeaders )(
+ ICoreWebView2HttpResponseHeaders * This,
+ /* [in] */ LPCWSTR name,
+ /* [retval][out] */ ICoreWebView2HttpHeadersCollectionIterator **iterator);
+
+ HRESULT ( STDMETHODCALLTYPE *GetIterator )(
+ ICoreWebView2HttpResponseHeaders * This,
+ /* [retval][out] */ ICoreWebView2HttpHeadersCollectionIterator **iterator);
+
+ END_INTERFACE
+ } ICoreWebView2HttpResponseHeadersVtbl;
+
+ interface ICoreWebView2HttpResponseHeaders
+ {
+ CONST_VTBL struct ICoreWebView2HttpResponseHeadersVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define ICoreWebView2HttpResponseHeaders_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define ICoreWebView2HttpResponseHeaders_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define ICoreWebView2HttpResponseHeaders_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define ICoreWebView2HttpResponseHeaders_AppendHeader(This,name,value) \
+ ( (This)->lpVtbl -> AppendHeader(This,name,value) )
+
+#define ICoreWebView2HttpResponseHeaders_Contains(This,name,contains) \
+ ( (This)->lpVtbl -> Contains(This,name,contains) )
+
+#define ICoreWebView2HttpResponseHeaders_GetHeader(This,name,value) \
+ ( (This)->lpVtbl -> GetHeader(This,name,value) )
+
+#define ICoreWebView2HttpResponseHeaders_GetHeaders(This,name,iterator) \
+ ( (This)->lpVtbl -> GetHeaders(This,name,iterator) )
+
+#define ICoreWebView2HttpResponseHeaders_GetIterator(This,iterator) \
+ ( (This)->lpVtbl -> GetIterator(This,iterator) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __ICoreWebView2HttpResponseHeaders_INTERFACE_DEFINED__ */
+
+
+#ifndef __ICoreWebView2Interop_INTERFACE_DEFINED__
+#define __ICoreWebView2Interop_INTERFACE_DEFINED__
+
+/* interface ICoreWebView2Interop */
+/* [unique][object][uuid] */
+
+
+EXTERN_C __declspec(selectany) const IID IID_ICoreWebView2Interop = {0x912b34a7,0xd10b,0x49c4,{0xaf,0x18,0x7c,0xb7,0xe6,0x04,0xe0,0x1a}};
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("912b34a7-d10b-49c4-af18-7cb7e604e01a")
+ ICoreWebView2Interop : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE AddHostObjectToScript(
+ /* [in] */ LPCWSTR name,
+ /* [in] */ VARIANT *object) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct ICoreWebView2InteropVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ ICoreWebView2Interop * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ ICoreWebView2Interop * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ ICoreWebView2Interop * This);
+
+ HRESULT ( STDMETHODCALLTYPE *AddHostObjectToScript )(
+ ICoreWebView2Interop * This,
+ /* [in] */ LPCWSTR name,
+ /* [in] */ VARIANT *object);
+
+ END_INTERFACE
+ } ICoreWebView2InteropVtbl;
+
+ interface ICoreWebView2Interop
+ {
+ CONST_VTBL struct ICoreWebView2InteropVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define ICoreWebView2Interop_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define ICoreWebView2Interop_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define ICoreWebView2Interop_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define ICoreWebView2Interop_AddHostObjectToScript(This,name,object) \
+ ( (This)->lpVtbl -> AddHostObjectToScript(This,name,object) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __ICoreWebView2Interop_INTERFACE_DEFINED__ */
+
+
+#ifndef __ICoreWebView2MoveFocusRequestedEventArgs_INTERFACE_DEFINED__
+#define __ICoreWebView2MoveFocusRequestedEventArgs_INTERFACE_DEFINED__
+
+/* interface ICoreWebView2MoveFocusRequestedEventArgs */
+/* [unique][object][uuid] */
+
+
+EXTERN_C __declspec(selectany) const IID IID_ICoreWebView2MoveFocusRequestedEventArgs = {0x2d6aa13b,0x3839,0x4a15,{0x92,0xfc,0xd8,0x8b,0x3c,0x0d,0x9c,0x9d}};
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("2d6aa13b-3839-4a15-92fc-d88b3c0d9c9d")
+ ICoreWebView2MoveFocusRequestedEventArgs : public IUnknown
+ {
+ public:
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_Reason(
+ /* [retval][out] */ COREWEBVIEW2_MOVE_FOCUS_REASON *reason) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_Handled(
+ /* [retval][out] */ BOOL *value) = 0;
+
+ virtual /* [propput] */ HRESULT STDMETHODCALLTYPE put_Handled(
+ /* [in] */ BOOL value) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct ICoreWebView2MoveFocusRequestedEventArgsVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ ICoreWebView2MoveFocusRequestedEventArgs * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ ICoreWebView2MoveFocusRequestedEventArgs * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ ICoreWebView2MoveFocusRequestedEventArgs * This);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_Reason )(
+ ICoreWebView2MoveFocusRequestedEventArgs * This,
+ /* [retval][out] */ COREWEBVIEW2_MOVE_FOCUS_REASON *reason);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_Handled )(
+ ICoreWebView2MoveFocusRequestedEventArgs * This,
+ /* [retval][out] */ BOOL *value);
+
+ /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_Handled )(
+ ICoreWebView2MoveFocusRequestedEventArgs * This,
+ /* [in] */ BOOL value);
+
+ END_INTERFACE
+ } ICoreWebView2MoveFocusRequestedEventArgsVtbl;
+
+ interface ICoreWebView2MoveFocusRequestedEventArgs
+ {
+ CONST_VTBL struct ICoreWebView2MoveFocusRequestedEventArgsVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define ICoreWebView2MoveFocusRequestedEventArgs_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define ICoreWebView2MoveFocusRequestedEventArgs_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define ICoreWebView2MoveFocusRequestedEventArgs_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define ICoreWebView2MoveFocusRequestedEventArgs_get_Reason(This,reason) \
+ ( (This)->lpVtbl -> get_Reason(This,reason) )
+
+#define ICoreWebView2MoveFocusRequestedEventArgs_get_Handled(This,value) \
+ ( (This)->lpVtbl -> get_Handled(This,value) )
+
+#define ICoreWebView2MoveFocusRequestedEventArgs_put_Handled(This,value) \
+ ( (This)->lpVtbl -> put_Handled(This,value) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __ICoreWebView2MoveFocusRequestedEventArgs_INTERFACE_DEFINED__ */
+
+
+#ifndef __ICoreWebView2MoveFocusRequestedEventHandler_INTERFACE_DEFINED__
+#define __ICoreWebView2MoveFocusRequestedEventHandler_INTERFACE_DEFINED__
+
+/* interface ICoreWebView2MoveFocusRequestedEventHandler */
+/* [unique][object][uuid] */
+
+
+EXTERN_C __declspec(selectany) const IID IID_ICoreWebView2MoveFocusRequestedEventHandler = {0x69035451,0x6dc7,0x4cb8,{0x9b,0xce,0xb2,0xbd,0x70,0xad,0x28,0x9f}};
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("69035451-6dc7-4cb8-9bce-b2bd70ad289f")
+ ICoreWebView2MoveFocusRequestedEventHandler : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE Invoke(
+ /* [in] */ ICoreWebView2Controller *sender,
+ /* [in] */ ICoreWebView2MoveFocusRequestedEventArgs *args) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct ICoreWebView2MoveFocusRequestedEventHandlerVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ ICoreWebView2MoveFocusRequestedEventHandler * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ ICoreWebView2MoveFocusRequestedEventHandler * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ ICoreWebView2MoveFocusRequestedEventHandler * This);
+
+ HRESULT ( STDMETHODCALLTYPE *Invoke )(
+ ICoreWebView2MoveFocusRequestedEventHandler * This,
+ /* [in] */ ICoreWebView2Controller *sender,
+ /* [in] */ ICoreWebView2MoveFocusRequestedEventArgs *args);
+
+ END_INTERFACE
+ } ICoreWebView2MoveFocusRequestedEventHandlerVtbl;
+
+ interface ICoreWebView2MoveFocusRequestedEventHandler
+ {
+ CONST_VTBL struct ICoreWebView2MoveFocusRequestedEventHandlerVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define ICoreWebView2MoveFocusRequestedEventHandler_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define ICoreWebView2MoveFocusRequestedEventHandler_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define ICoreWebView2MoveFocusRequestedEventHandler_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define ICoreWebView2MoveFocusRequestedEventHandler_Invoke(This,sender,args) \
+ ( (This)->lpVtbl -> Invoke(This,sender,args) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __ICoreWebView2MoveFocusRequestedEventHandler_INTERFACE_DEFINED__ */
+
+
+#ifndef __ICoreWebView2NavigationCompletedEventArgs_INTERFACE_DEFINED__
+#define __ICoreWebView2NavigationCompletedEventArgs_INTERFACE_DEFINED__
+
+/* interface ICoreWebView2NavigationCompletedEventArgs */
+/* [unique][object][uuid] */
+
+
+EXTERN_C __declspec(selectany) const IID IID_ICoreWebView2NavigationCompletedEventArgs = {0x30d68b7d,0x20d9,0x4752,{0xa9,0xca,0xec,0x84,0x48,0xfb,0xb5,0xc1}};
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("30d68b7d-20d9-4752-a9ca-ec8448fbb5c1")
+ ICoreWebView2NavigationCompletedEventArgs : public IUnknown
+ {
+ public:
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_IsSuccess(
+ /* [retval][out] */ BOOL *isSuccess) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_WebErrorStatus(
+ /* [retval][out] */ COREWEBVIEW2_WEB_ERROR_STATUS *webErrorStatus) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_NavigationId(
+ /* [retval][out] */ UINT64 *navigationId) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct ICoreWebView2NavigationCompletedEventArgsVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ ICoreWebView2NavigationCompletedEventArgs * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ ICoreWebView2NavigationCompletedEventArgs * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ ICoreWebView2NavigationCompletedEventArgs * This);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_IsSuccess )(
+ ICoreWebView2NavigationCompletedEventArgs * This,
+ /* [retval][out] */ BOOL *isSuccess);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_WebErrorStatus )(
+ ICoreWebView2NavigationCompletedEventArgs * This,
+ /* [retval][out] */ COREWEBVIEW2_WEB_ERROR_STATUS *webErrorStatus);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_NavigationId )(
+ ICoreWebView2NavigationCompletedEventArgs * This,
+ /* [retval][out] */ UINT64 *navigationId);
+
+ END_INTERFACE
+ } ICoreWebView2NavigationCompletedEventArgsVtbl;
+
+ interface ICoreWebView2NavigationCompletedEventArgs
+ {
+ CONST_VTBL struct ICoreWebView2NavigationCompletedEventArgsVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define ICoreWebView2NavigationCompletedEventArgs_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define ICoreWebView2NavigationCompletedEventArgs_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define ICoreWebView2NavigationCompletedEventArgs_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define ICoreWebView2NavigationCompletedEventArgs_get_IsSuccess(This,isSuccess) \
+ ( (This)->lpVtbl -> get_IsSuccess(This,isSuccess) )
+
+#define ICoreWebView2NavigationCompletedEventArgs_get_WebErrorStatus(This,webErrorStatus) \
+ ( (This)->lpVtbl -> get_WebErrorStatus(This,webErrorStatus) )
+
+#define ICoreWebView2NavigationCompletedEventArgs_get_NavigationId(This,navigationId) \
+ ( (This)->lpVtbl -> get_NavigationId(This,navigationId) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __ICoreWebView2NavigationCompletedEventArgs_INTERFACE_DEFINED__ */
+
+
+#ifndef __ICoreWebView2NavigationCompletedEventHandler_INTERFACE_DEFINED__
+#define __ICoreWebView2NavigationCompletedEventHandler_INTERFACE_DEFINED__
+
+/* interface ICoreWebView2NavigationCompletedEventHandler */
+/* [unique][object][uuid] */
+
+
+EXTERN_C __declspec(selectany) const IID IID_ICoreWebView2NavigationCompletedEventHandler = {0xd33a35bf,0x1c49,0x4f98,{0x93,0xab,0x00,0x6e,0x05,0x33,0xfe,0x1c}};
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("d33a35bf-1c49-4f98-93ab-006e0533fe1c")
+ ICoreWebView2NavigationCompletedEventHandler : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE Invoke(
+ /* [in] */ ICoreWebView2 *sender,
+ /* [in] */ ICoreWebView2NavigationCompletedEventArgs *args) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct ICoreWebView2NavigationCompletedEventHandlerVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ ICoreWebView2NavigationCompletedEventHandler * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ ICoreWebView2NavigationCompletedEventHandler * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ ICoreWebView2NavigationCompletedEventHandler * This);
+
+ HRESULT ( STDMETHODCALLTYPE *Invoke )(
+ ICoreWebView2NavigationCompletedEventHandler * This,
+ /* [in] */ ICoreWebView2 *sender,
+ /* [in] */ ICoreWebView2NavigationCompletedEventArgs *args);
+
+ END_INTERFACE
+ } ICoreWebView2NavigationCompletedEventHandlerVtbl;
+
+ interface ICoreWebView2NavigationCompletedEventHandler
+ {
+ CONST_VTBL struct ICoreWebView2NavigationCompletedEventHandlerVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define ICoreWebView2NavigationCompletedEventHandler_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define ICoreWebView2NavigationCompletedEventHandler_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define ICoreWebView2NavigationCompletedEventHandler_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define ICoreWebView2NavigationCompletedEventHandler_Invoke(This,sender,args) \
+ ( (This)->lpVtbl -> Invoke(This,sender,args) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __ICoreWebView2NavigationCompletedEventHandler_INTERFACE_DEFINED__ */
+
+
+#ifndef __ICoreWebView2NavigationStartingEventArgs_INTERFACE_DEFINED__
+#define __ICoreWebView2NavigationStartingEventArgs_INTERFACE_DEFINED__
+
+/* interface ICoreWebView2NavigationStartingEventArgs */
+/* [unique][object][uuid] */
+
+
+EXTERN_C __declspec(selectany) const IID IID_ICoreWebView2NavigationStartingEventArgs = {0x5b495469,0xe119,0x438a,{0x9b,0x18,0x76,0x04,0xf2,0x5f,0x2e,0x49}};
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("5b495469-e119-438a-9b18-7604f25f2e49")
+ ICoreWebView2NavigationStartingEventArgs : public IUnknown
+ {
+ public:
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_Uri(
+ /* [retval][out] */ LPWSTR *uri) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_IsUserInitiated(
+ /* [retval][out] */ BOOL *isUserInitiated) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_IsRedirected(
+ /* [retval][out] */ BOOL *isRedirected) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_RequestHeaders(
+ /* [retval][out] */ ICoreWebView2HttpRequestHeaders **requestHeaders) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_Cancel(
+ /* [retval][out] */ BOOL *cancel) = 0;
+
+ virtual /* [propput] */ HRESULT STDMETHODCALLTYPE put_Cancel(
+ /* [in] */ BOOL cancel) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_NavigationId(
+ /* [retval][out] */ UINT64 *navigationId) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct ICoreWebView2NavigationStartingEventArgsVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ ICoreWebView2NavigationStartingEventArgs * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ ICoreWebView2NavigationStartingEventArgs * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ ICoreWebView2NavigationStartingEventArgs * This);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_Uri )(
+ ICoreWebView2NavigationStartingEventArgs * This,
+ /* [retval][out] */ LPWSTR *uri);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_IsUserInitiated )(
+ ICoreWebView2NavigationStartingEventArgs * This,
+ /* [retval][out] */ BOOL *isUserInitiated);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_IsRedirected )(
+ ICoreWebView2NavigationStartingEventArgs * This,
+ /* [retval][out] */ BOOL *isRedirected);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_RequestHeaders )(
+ ICoreWebView2NavigationStartingEventArgs * This,
+ /* [retval][out] */ ICoreWebView2HttpRequestHeaders **requestHeaders);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_Cancel )(
+ ICoreWebView2NavigationStartingEventArgs * This,
+ /* [retval][out] */ BOOL *cancel);
+
+ /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_Cancel )(
+ ICoreWebView2NavigationStartingEventArgs * This,
+ /* [in] */ BOOL cancel);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_NavigationId )(
+ ICoreWebView2NavigationStartingEventArgs * This,
+ /* [retval][out] */ UINT64 *navigationId);
+
+ END_INTERFACE
+ } ICoreWebView2NavigationStartingEventArgsVtbl;
+
+ interface ICoreWebView2NavigationStartingEventArgs
+ {
+ CONST_VTBL struct ICoreWebView2NavigationStartingEventArgsVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define ICoreWebView2NavigationStartingEventArgs_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define ICoreWebView2NavigationStartingEventArgs_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define ICoreWebView2NavigationStartingEventArgs_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define ICoreWebView2NavigationStartingEventArgs_get_Uri(This,uri) \
+ ( (This)->lpVtbl -> get_Uri(This,uri) )
+
+#define ICoreWebView2NavigationStartingEventArgs_get_IsUserInitiated(This,isUserInitiated) \
+ ( (This)->lpVtbl -> get_IsUserInitiated(This,isUserInitiated) )
+
+#define ICoreWebView2NavigationStartingEventArgs_get_IsRedirected(This,isRedirected) \
+ ( (This)->lpVtbl -> get_IsRedirected(This,isRedirected) )
+
+#define ICoreWebView2NavigationStartingEventArgs_get_RequestHeaders(This,requestHeaders) \
+ ( (This)->lpVtbl -> get_RequestHeaders(This,requestHeaders) )
+
+#define ICoreWebView2NavigationStartingEventArgs_get_Cancel(This,cancel) \
+ ( (This)->lpVtbl -> get_Cancel(This,cancel) )
+
+#define ICoreWebView2NavigationStartingEventArgs_put_Cancel(This,cancel) \
+ ( (This)->lpVtbl -> put_Cancel(This,cancel) )
+
+#define ICoreWebView2NavigationStartingEventArgs_get_NavigationId(This,navigationId) \
+ ( (This)->lpVtbl -> get_NavigationId(This,navigationId) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __ICoreWebView2NavigationStartingEventArgs_INTERFACE_DEFINED__ */
+
+
+#ifndef __ICoreWebView2NavigationStartingEventHandler_INTERFACE_DEFINED__
+#define __ICoreWebView2NavigationStartingEventHandler_INTERFACE_DEFINED__
+
+/* interface ICoreWebView2NavigationStartingEventHandler */
+/* [unique][object][uuid] */
+
+
+EXTERN_C __declspec(selectany) const IID IID_ICoreWebView2NavigationStartingEventHandler = {0x9adbe429,0xf36d,0x432b,{0x9d,0xdc,0xf8,0x88,0x1f,0xbd,0x76,0xe3}};
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("9adbe429-f36d-432b-9ddc-f8881fbd76e3")
+ ICoreWebView2NavigationStartingEventHandler : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE Invoke(
+ /* [in] */ ICoreWebView2 *sender,
+ /* [in] */ ICoreWebView2NavigationStartingEventArgs *args) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct ICoreWebView2NavigationStartingEventHandlerVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ ICoreWebView2NavigationStartingEventHandler * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ ICoreWebView2NavigationStartingEventHandler * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ ICoreWebView2NavigationStartingEventHandler * This);
+
+ HRESULT ( STDMETHODCALLTYPE *Invoke )(
+ ICoreWebView2NavigationStartingEventHandler * This,
+ /* [in] */ ICoreWebView2 *sender,
+ /* [in] */ ICoreWebView2NavigationStartingEventArgs *args);
+
+ END_INTERFACE
+ } ICoreWebView2NavigationStartingEventHandlerVtbl;
+
+ interface ICoreWebView2NavigationStartingEventHandler
+ {
+ CONST_VTBL struct ICoreWebView2NavigationStartingEventHandlerVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define ICoreWebView2NavigationStartingEventHandler_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define ICoreWebView2NavigationStartingEventHandler_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define ICoreWebView2NavigationStartingEventHandler_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define ICoreWebView2NavigationStartingEventHandler_Invoke(This,sender,args) \
+ ( (This)->lpVtbl -> Invoke(This,sender,args) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __ICoreWebView2NavigationStartingEventHandler_INTERFACE_DEFINED__ */
+
+
+#ifndef __ICoreWebView2NewBrowserVersionAvailableEventHandler_INTERFACE_DEFINED__
+#define __ICoreWebView2NewBrowserVersionAvailableEventHandler_INTERFACE_DEFINED__
+
+/* interface ICoreWebView2NewBrowserVersionAvailableEventHandler */
+/* [unique][object][uuid] */
+
+
+EXTERN_C __declspec(selectany) const IID IID_ICoreWebView2NewBrowserVersionAvailableEventHandler = {0xf9a2976e,0xd34e,0x44fc,{0xad,0xee,0x81,0xb6,0xb5,0x7c,0xa9,0x14}};
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("f9a2976e-d34e-44fc-adee-81b6b57ca914")
+ ICoreWebView2NewBrowserVersionAvailableEventHandler : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE Invoke(
+ /* [in] */ ICoreWebView2Environment *sender,
+ /* [in] */ IUnknown *args) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct ICoreWebView2NewBrowserVersionAvailableEventHandlerVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ ICoreWebView2NewBrowserVersionAvailableEventHandler * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ ICoreWebView2NewBrowserVersionAvailableEventHandler * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ ICoreWebView2NewBrowserVersionAvailableEventHandler * This);
+
+ HRESULT ( STDMETHODCALLTYPE *Invoke )(
+ ICoreWebView2NewBrowserVersionAvailableEventHandler * This,
+ /* [in] */ ICoreWebView2Environment *sender,
+ /* [in] */ IUnknown *args);
+
+ END_INTERFACE
+ } ICoreWebView2NewBrowserVersionAvailableEventHandlerVtbl;
+
+ interface ICoreWebView2NewBrowserVersionAvailableEventHandler
+ {
+ CONST_VTBL struct ICoreWebView2NewBrowserVersionAvailableEventHandlerVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define ICoreWebView2NewBrowserVersionAvailableEventHandler_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define ICoreWebView2NewBrowserVersionAvailableEventHandler_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define ICoreWebView2NewBrowserVersionAvailableEventHandler_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define ICoreWebView2NewBrowserVersionAvailableEventHandler_Invoke(This,sender,args) \
+ ( (This)->lpVtbl -> Invoke(This,sender,args) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __ICoreWebView2NewBrowserVersionAvailableEventHandler_INTERFACE_DEFINED__ */
+
+
+#ifndef __ICoreWebView2NewWindowRequestedEventArgs_INTERFACE_DEFINED__
+#define __ICoreWebView2NewWindowRequestedEventArgs_INTERFACE_DEFINED__
+
+/* interface ICoreWebView2NewWindowRequestedEventArgs */
+/* [unique][object][uuid] */
+
+
+EXTERN_C __declspec(selectany) const IID IID_ICoreWebView2NewWindowRequestedEventArgs = {0x34acb11c,0xfc37,0x4418,{0x91,0x32,0xf9,0xc2,0x1d,0x1e,0xaf,0xb9}};
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("34acb11c-fc37-4418-9132-f9c21d1eafb9")
+ ICoreWebView2NewWindowRequestedEventArgs : public IUnknown
+ {
+ public:
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_Uri(
+ /* [retval][out] */ LPWSTR *uri) = 0;
+
+ virtual /* [propput] */ HRESULT STDMETHODCALLTYPE put_NewWindow(
+ /* [in] */ ICoreWebView2 *newWindow) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_NewWindow(
+ /* [retval][out] */ ICoreWebView2 **newWindow) = 0;
+
+ virtual /* [propput] */ HRESULT STDMETHODCALLTYPE put_Handled(
+ /* [in] */ BOOL handled) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_Handled(
+ /* [retval][out] */ BOOL *handled) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_IsUserInitiated(
+ /* [retval][out] */ BOOL *isUserInitiated) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetDeferral(
+ /* [retval][out] */ ICoreWebView2Deferral **deferral) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_WindowFeatures(
+ /* [retval][out] */ ICoreWebView2WindowFeatures **value) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct ICoreWebView2NewWindowRequestedEventArgsVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ ICoreWebView2NewWindowRequestedEventArgs * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ ICoreWebView2NewWindowRequestedEventArgs * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ ICoreWebView2NewWindowRequestedEventArgs * This);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_Uri )(
+ ICoreWebView2NewWindowRequestedEventArgs * This,
+ /* [retval][out] */ LPWSTR *uri);
+
+ /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_NewWindow )(
+ ICoreWebView2NewWindowRequestedEventArgs * This,
+ /* [in] */ ICoreWebView2 *newWindow);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_NewWindow )(
+ ICoreWebView2NewWindowRequestedEventArgs * This,
+ /* [retval][out] */ ICoreWebView2 **newWindow);
+
+ /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_Handled )(
+ ICoreWebView2NewWindowRequestedEventArgs * This,
+ /* [in] */ BOOL handled);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_Handled )(
+ ICoreWebView2NewWindowRequestedEventArgs * This,
+ /* [retval][out] */ BOOL *handled);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_IsUserInitiated )(
+ ICoreWebView2NewWindowRequestedEventArgs * This,
+ /* [retval][out] */ BOOL *isUserInitiated);
+
+ HRESULT ( STDMETHODCALLTYPE *GetDeferral )(
+ ICoreWebView2NewWindowRequestedEventArgs * This,
+ /* [retval][out] */ ICoreWebView2Deferral **deferral);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_WindowFeatures )(
+ ICoreWebView2NewWindowRequestedEventArgs * This,
+ /* [retval][out] */ ICoreWebView2WindowFeatures **value);
+
+ END_INTERFACE
+ } ICoreWebView2NewWindowRequestedEventArgsVtbl;
+
+ interface ICoreWebView2NewWindowRequestedEventArgs
+ {
+ CONST_VTBL struct ICoreWebView2NewWindowRequestedEventArgsVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define ICoreWebView2NewWindowRequestedEventArgs_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define ICoreWebView2NewWindowRequestedEventArgs_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define ICoreWebView2NewWindowRequestedEventArgs_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define ICoreWebView2NewWindowRequestedEventArgs_get_Uri(This,uri) \
+ ( (This)->lpVtbl -> get_Uri(This,uri) )
+
+#define ICoreWebView2NewWindowRequestedEventArgs_put_NewWindow(This,newWindow) \
+ ( (This)->lpVtbl -> put_NewWindow(This,newWindow) )
+
+#define ICoreWebView2NewWindowRequestedEventArgs_get_NewWindow(This,newWindow) \
+ ( (This)->lpVtbl -> get_NewWindow(This,newWindow) )
+
+#define ICoreWebView2NewWindowRequestedEventArgs_put_Handled(This,handled) \
+ ( (This)->lpVtbl -> put_Handled(This,handled) )
+
+#define ICoreWebView2NewWindowRequestedEventArgs_get_Handled(This,handled) \
+ ( (This)->lpVtbl -> get_Handled(This,handled) )
+
+#define ICoreWebView2NewWindowRequestedEventArgs_get_IsUserInitiated(This,isUserInitiated) \
+ ( (This)->lpVtbl -> get_IsUserInitiated(This,isUserInitiated) )
+
+#define ICoreWebView2NewWindowRequestedEventArgs_GetDeferral(This,deferral) \
+ ( (This)->lpVtbl -> GetDeferral(This,deferral) )
+
+#define ICoreWebView2NewWindowRequestedEventArgs_get_WindowFeatures(This,value) \
+ ( (This)->lpVtbl -> get_WindowFeatures(This,value) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __ICoreWebView2NewWindowRequestedEventArgs_INTERFACE_DEFINED__ */
+
+
+#ifndef __ICoreWebView2NewWindowRequestedEventHandler_INTERFACE_DEFINED__
+#define __ICoreWebView2NewWindowRequestedEventHandler_INTERFACE_DEFINED__
+
+/* interface ICoreWebView2NewWindowRequestedEventHandler */
+/* [unique][object][uuid] */
+
+
+EXTERN_C __declspec(selectany) const IID IID_ICoreWebView2NewWindowRequestedEventHandler = {0xd4c185fe,0xc81c,0x4989,{0x97,0xaf,0x2d,0x3f,0xa7,0xab,0x56,0x51}};
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("d4c185fe-c81c-4989-97af-2d3fa7ab5651")
+ ICoreWebView2NewWindowRequestedEventHandler : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE Invoke(
+ /* [in] */ ICoreWebView2 *sender,
+ /* [in] */ ICoreWebView2NewWindowRequestedEventArgs *args) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct ICoreWebView2NewWindowRequestedEventHandlerVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ ICoreWebView2NewWindowRequestedEventHandler * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ ICoreWebView2NewWindowRequestedEventHandler * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ ICoreWebView2NewWindowRequestedEventHandler * This);
+
+ HRESULT ( STDMETHODCALLTYPE *Invoke )(
+ ICoreWebView2NewWindowRequestedEventHandler * This,
+ /* [in] */ ICoreWebView2 *sender,
+ /* [in] */ ICoreWebView2NewWindowRequestedEventArgs *args);
+
+ END_INTERFACE
+ } ICoreWebView2NewWindowRequestedEventHandlerVtbl;
+
+ interface ICoreWebView2NewWindowRequestedEventHandler
+ {
+ CONST_VTBL struct ICoreWebView2NewWindowRequestedEventHandlerVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define ICoreWebView2NewWindowRequestedEventHandler_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define ICoreWebView2NewWindowRequestedEventHandler_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define ICoreWebView2NewWindowRequestedEventHandler_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define ICoreWebView2NewWindowRequestedEventHandler_Invoke(This,sender,args) \
+ ( (This)->lpVtbl -> Invoke(This,sender,args) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __ICoreWebView2NewWindowRequestedEventHandler_INTERFACE_DEFINED__ */
+
+
+#ifndef __ICoreWebView2PermissionRequestedEventArgs_INTERFACE_DEFINED__
+#define __ICoreWebView2PermissionRequestedEventArgs_INTERFACE_DEFINED__
+
+/* interface ICoreWebView2PermissionRequestedEventArgs */
+/* [unique][object][uuid] */
+
+
+EXTERN_C __declspec(selectany) const IID IID_ICoreWebView2PermissionRequestedEventArgs = {0x973ae2ef,0xff18,0x4894,{0x8f,0xb2,0x3c,0x75,0x8f,0x04,0x68,0x10}};
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("973ae2ef-ff18-4894-8fb2-3c758f046810")
+ ICoreWebView2PermissionRequestedEventArgs : public IUnknown
+ {
+ public:
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_Uri(
+ /* [retval][out] */ LPWSTR *uri) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_PermissionKind(
+ /* [retval][out] */ COREWEBVIEW2_PERMISSION_KIND *permissionKind) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_IsUserInitiated(
+ /* [retval][out] */ BOOL *isUserInitiated) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_State(
+ /* [retval][out] */ COREWEBVIEW2_PERMISSION_STATE *state) = 0;
+
+ virtual /* [propput] */ HRESULT STDMETHODCALLTYPE put_State(
+ /* [in] */ COREWEBVIEW2_PERMISSION_STATE state) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetDeferral(
+ /* [retval][out] */ ICoreWebView2Deferral **deferral) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct ICoreWebView2PermissionRequestedEventArgsVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ ICoreWebView2PermissionRequestedEventArgs * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ ICoreWebView2PermissionRequestedEventArgs * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ ICoreWebView2PermissionRequestedEventArgs * This);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_Uri )(
+ ICoreWebView2PermissionRequestedEventArgs * This,
+ /* [retval][out] */ LPWSTR *uri);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_PermissionKind )(
+ ICoreWebView2PermissionRequestedEventArgs * This,
+ /* [retval][out] */ COREWEBVIEW2_PERMISSION_KIND *permissionKind);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_IsUserInitiated )(
+ ICoreWebView2PermissionRequestedEventArgs * This,
+ /* [retval][out] */ BOOL *isUserInitiated);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_State )(
+ ICoreWebView2PermissionRequestedEventArgs * This,
+ /* [retval][out] */ COREWEBVIEW2_PERMISSION_STATE *state);
+
+ /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_State )(
+ ICoreWebView2PermissionRequestedEventArgs * This,
+ /* [in] */ COREWEBVIEW2_PERMISSION_STATE state);
+
+ HRESULT ( STDMETHODCALLTYPE *GetDeferral )(
+ ICoreWebView2PermissionRequestedEventArgs * This,
+ /* [retval][out] */ ICoreWebView2Deferral **deferral);
+
+ END_INTERFACE
+ } ICoreWebView2PermissionRequestedEventArgsVtbl;
+
+ interface ICoreWebView2PermissionRequestedEventArgs
+ {
+ CONST_VTBL struct ICoreWebView2PermissionRequestedEventArgsVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define ICoreWebView2PermissionRequestedEventArgs_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define ICoreWebView2PermissionRequestedEventArgs_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define ICoreWebView2PermissionRequestedEventArgs_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define ICoreWebView2PermissionRequestedEventArgs_get_Uri(This,uri) \
+ ( (This)->lpVtbl -> get_Uri(This,uri) )
+
+#define ICoreWebView2PermissionRequestedEventArgs_get_PermissionKind(This,permissionKind) \
+ ( (This)->lpVtbl -> get_PermissionKind(This,permissionKind) )
+
+#define ICoreWebView2PermissionRequestedEventArgs_get_IsUserInitiated(This,isUserInitiated) \
+ ( (This)->lpVtbl -> get_IsUserInitiated(This,isUserInitiated) )
+
+#define ICoreWebView2PermissionRequestedEventArgs_get_State(This,state) \
+ ( (This)->lpVtbl -> get_State(This,state) )
+
+#define ICoreWebView2PermissionRequestedEventArgs_put_State(This,state) \
+ ( (This)->lpVtbl -> put_State(This,state) )
+
+#define ICoreWebView2PermissionRequestedEventArgs_GetDeferral(This,deferral) \
+ ( (This)->lpVtbl -> GetDeferral(This,deferral) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __ICoreWebView2PermissionRequestedEventArgs_INTERFACE_DEFINED__ */
+
+
+#ifndef __ICoreWebView2PermissionRequestedEventHandler_INTERFACE_DEFINED__
+#define __ICoreWebView2PermissionRequestedEventHandler_INTERFACE_DEFINED__
+
+/* interface ICoreWebView2PermissionRequestedEventHandler */
+/* [unique][object][uuid] */
+
+
+EXTERN_C __declspec(selectany) const IID IID_ICoreWebView2PermissionRequestedEventHandler = {0x15e1c6a3,0xc72a,0x4df3,{0x91,0xd7,0xd0,0x97,0xfb,0xec,0x6b,0xfd}};
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("15e1c6a3-c72a-4df3-91d7-d097fbec6bfd")
+ ICoreWebView2PermissionRequestedEventHandler : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE Invoke(
+ /* [in] */ ICoreWebView2 *sender,
+ /* [in] */ ICoreWebView2PermissionRequestedEventArgs *args) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct ICoreWebView2PermissionRequestedEventHandlerVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ ICoreWebView2PermissionRequestedEventHandler * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ ICoreWebView2PermissionRequestedEventHandler * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ ICoreWebView2PermissionRequestedEventHandler * This);
+
+ HRESULT ( STDMETHODCALLTYPE *Invoke )(
+ ICoreWebView2PermissionRequestedEventHandler * This,
+ /* [in] */ ICoreWebView2 *sender,
+ /* [in] */ ICoreWebView2PermissionRequestedEventArgs *args);
+
+ END_INTERFACE
+ } ICoreWebView2PermissionRequestedEventHandlerVtbl;
+
+ interface ICoreWebView2PermissionRequestedEventHandler
+ {
+ CONST_VTBL struct ICoreWebView2PermissionRequestedEventHandlerVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define ICoreWebView2PermissionRequestedEventHandler_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define ICoreWebView2PermissionRequestedEventHandler_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define ICoreWebView2PermissionRequestedEventHandler_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define ICoreWebView2PermissionRequestedEventHandler_Invoke(This,sender,args) \
+ ( (This)->lpVtbl -> Invoke(This,sender,args) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __ICoreWebView2PermissionRequestedEventHandler_INTERFACE_DEFINED__ */
+
+
+#ifndef __ICoreWebView2PointerInfo_INTERFACE_DEFINED__
+#define __ICoreWebView2PointerInfo_INTERFACE_DEFINED__
+
+/* interface ICoreWebView2PointerInfo */
+/* [unique][object][uuid] */
+
+
+EXTERN_C __declspec(selectany) const IID IID_ICoreWebView2PointerInfo = {0xe6995887,0xd10d,0x4f5d,{0x93,0x59,0x4c,0xe4,0x6e,0x4f,0x96,0xb9}};
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("e6995887-d10d-4f5d-9359-4ce46e4f96b9")
+ ICoreWebView2PointerInfo : public IUnknown
+ {
+ public:
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_PointerKind(
+ /* [retval][out] */ DWORD *pointerKind) = 0;
+
+ virtual /* [propput] */ HRESULT STDMETHODCALLTYPE put_PointerKind(
+ /* [in] */ DWORD pointerKind) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_PointerId(
+ /* [retval][out] */ UINT32 *pointerId) = 0;
+
+ virtual /* [propput] */ HRESULT STDMETHODCALLTYPE put_PointerId(
+ /* [in] */ UINT32 pointerId) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_FrameId(
+ /* [retval][out] */ UINT32 *frameId) = 0;
+
+ virtual /* [propput] */ HRESULT STDMETHODCALLTYPE put_FrameId(
+ /* [in] */ UINT32 frameId) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_PointerFlags(
+ /* [retval][out] */ UINT32 *pointerFlags) = 0;
+
+ virtual /* [propput] */ HRESULT STDMETHODCALLTYPE put_PointerFlags(
+ /* [in] */ UINT32 pointerFlags) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_PointerDeviceRect(
+ /* [retval][out] */ RECT *pointerDeviceRect) = 0;
+
+ virtual /* [propput] */ HRESULT STDMETHODCALLTYPE put_PointerDeviceRect(
+ /* [in] */ RECT pointerDeviceRect) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_DisplayRect(
+ /* [retval][out] */ RECT *displayRect) = 0;
+
+ virtual /* [propput] */ HRESULT STDMETHODCALLTYPE put_DisplayRect(
+ /* [in] */ RECT displayRect) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_PixelLocation(
+ /* [retval][out] */ POINT *pixelLocation) = 0;
+
+ virtual /* [propput] */ HRESULT STDMETHODCALLTYPE put_PixelLocation(
+ /* [in] */ POINT pixelLocation) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_HimetricLocation(
+ /* [retval][out] */ POINT *himetricLocation) = 0;
+
+ virtual /* [propput] */ HRESULT STDMETHODCALLTYPE put_HimetricLocation(
+ /* [in] */ POINT himetricLocation) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_PixelLocationRaw(
+ /* [retval][out] */ POINT *pixelLocationRaw) = 0;
+
+ virtual /* [propput] */ HRESULT STDMETHODCALLTYPE put_PixelLocationRaw(
+ /* [in] */ POINT pixelLocationRaw) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_HimetricLocationRaw(
+ /* [retval][out] */ POINT *himetricLocationRaw) = 0;
+
+ virtual /* [propput] */ HRESULT STDMETHODCALLTYPE put_HimetricLocationRaw(
+ /* [in] */ POINT himetricLocationRaw) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_Time(
+ /* [retval][out] */ DWORD *time) = 0;
+
+ virtual /* [propput] */ HRESULT STDMETHODCALLTYPE put_Time(
+ /* [in] */ DWORD time) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_HistoryCount(
+ /* [retval][out] */ UINT32 *historyCount) = 0;
+
+ virtual /* [propput] */ HRESULT STDMETHODCALLTYPE put_HistoryCount(
+ /* [in] */ UINT32 historyCount) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_InputData(
+ /* [retval][out] */ INT32 *inputData) = 0;
+
+ virtual /* [propput] */ HRESULT STDMETHODCALLTYPE put_InputData(
+ /* [in] */ INT32 inputData) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_KeyStates(
+ /* [retval][out] */ DWORD *keyStates) = 0;
+
+ virtual /* [propput] */ HRESULT STDMETHODCALLTYPE put_KeyStates(
+ /* [in] */ DWORD keyStates) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_PerformanceCount(
+ /* [retval][out] */ UINT64 *performanceCount) = 0;
+
+ virtual /* [propput] */ HRESULT STDMETHODCALLTYPE put_PerformanceCount(
+ /* [in] */ UINT64 performanceCount) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_ButtonChangeKind(
+ /* [retval][out] */ INT32 *buttonChangeKind) = 0;
+
+ virtual /* [propput] */ HRESULT STDMETHODCALLTYPE put_ButtonChangeKind(
+ /* [in] */ INT32 buttonChangeKind) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_PenFlags(
+ /* [retval][out] */ UINT32 *penFLags) = 0;
+
+ virtual /* [propput] */ HRESULT STDMETHODCALLTYPE put_PenFlags(
+ /* [in] */ UINT32 penFLags) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_PenMask(
+ /* [retval][out] */ UINT32 *penMask) = 0;
+
+ virtual /* [propput] */ HRESULT STDMETHODCALLTYPE put_PenMask(
+ /* [in] */ UINT32 penMask) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_PenPressure(
+ /* [retval][out] */ UINT32 *penPressure) = 0;
+
+ virtual /* [propput] */ HRESULT STDMETHODCALLTYPE put_PenPressure(
+ /* [in] */ UINT32 penPressure) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_PenRotation(
+ /* [retval][out] */ UINT32 *penRotation) = 0;
+
+ virtual /* [propput] */ HRESULT STDMETHODCALLTYPE put_PenRotation(
+ /* [in] */ UINT32 penRotation) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_PenTiltX(
+ /* [retval][out] */ INT32 *penTiltX) = 0;
+
+ virtual /* [propput] */ HRESULT STDMETHODCALLTYPE put_PenTiltX(
+ /* [in] */ INT32 penTiltX) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_PenTiltY(
+ /* [retval][out] */ INT32 *penTiltY) = 0;
+
+ virtual /* [propput] */ HRESULT STDMETHODCALLTYPE put_PenTiltY(
+ /* [in] */ INT32 penTiltY) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_TouchFlags(
+ /* [retval][out] */ UINT32 *touchFlags) = 0;
+
+ virtual /* [propput] */ HRESULT STDMETHODCALLTYPE put_TouchFlags(
+ /* [in] */ UINT32 touchFlags) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_TouchMask(
+ /* [retval][out] */ UINT32 *touchMask) = 0;
+
+ virtual /* [propput] */ HRESULT STDMETHODCALLTYPE put_TouchMask(
+ /* [in] */ UINT32 touchMask) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_TouchContact(
+ /* [retval][out] */ RECT *touchContact) = 0;
+
+ virtual /* [propput] */ HRESULT STDMETHODCALLTYPE put_TouchContact(
+ /* [in] */ RECT touchContact) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_TouchContactRaw(
+ /* [retval][out] */ RECT *touchContactRaw) = 0;
+
+ virtual /* [propput] */ HRESULT STDMETHODCALLTYPE put_TouchContactRaw(
+ /* [in] */ RECT touchContactRaw) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_TouchOrientation(
+ /* [retval][out] */ UINT32 *touchOrientation) = 0;
+
+ virtual /* [propput] */ HRESULT STDMETHODCALLTYPE put_TouchOrientation(
+ /* [in] */ UINT32 touchOrientation) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_TouchPressure(
+ /* [retval][out] */ UINT32 *touchPressure) = 0;
+
+ virtual /* [propput] */ HRESULT STDMETHODCALLTYPE put_TouchPressure(
+ /* [in] */ UINT32 touchPressure) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct ICoreWebView2PointerInfoVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ ICoreWebView2PointerInfo * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ ICoreWebView2PointerInfo * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ ICoreWebView2PointerInfo * This);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_PointerKind )(
+ ICoreWebView2PointerInfo * This,
+ /* [retval][out] */ DWORD *pointerKind);
+
+ /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_PointerKind )(
+ ICoreWebView2PointerInfo * This,
+ /* [in] */ DWORD pointerKind);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_PointerId )(
+ ICoreWebView2PointerInfo * This,
+ /* [retval][out] */ UINT32 *pointerId);
+
+ /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_PointerId )(
+ ICoreWebView2PointerInfo * This,
+ /* [in] */ UINT32 pointerId);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_FrameId )(
+ ICoreWebView2PointerInfo * This,
+ /* [retval][out] */ UINT32 *frameId);
+
+ /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_FrameId )(
+ ICoreWebView2PointerInfo * This,
+ /* [in] */ UINT32 frameId);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_PointerFlags )(
+ ICoreWebView2PointerInfo * This,
+ /* [retval][out] */ UINT32 *pointerFlags);
+
+ /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_PointerFlags )(
+ ICoreWebView2PointerInfo * This,
+ /* [in] */ UINT32 pointerFlags);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_PointerDeviceRect )(
+ ICoreWebView2PointerInfo * This,
+ /* [retval][out] */ RECT *pointerDeviceRect);
+
+ /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_PointerDeviceRect )(
+ ICoreWebView2PointerInfo * This,
+ /* [in] */ RECT pointerDeviceRect);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_DisplayRect )(
+ ICoreWebView2PointerInfo * This,
+ /* [retval][out] */ RECT *displayRect);
+
+ /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_DisplayRect )(
+ ICoreWebView2PointerInfo * This,
+ /* [in] */ RECT displayRect);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_PixelLocation )(
+ ICoreWebView2PointerInfo * This,
+ /* [retval][out] */ POINT *pixelLocation);
+
+ /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_PixelLocation )(
+ ICoreWebView2PointerInfo * This,
+ /* [in] */ POINT pixelLocation);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_HimetricLocation )(
+ ICoreWebView2PointerInfo * This,
+ /* [retval][out] */ POINT *himetricLocation);
+
+ /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_HimetricLocation )(
+ ICoreWebView2PointerInfo * This,
+ /* [in] */ POINT himetricLocation);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_PixelLocationRaw )(
+ ICoreWebView2PointerInfo * This,
+ /* [retval][out] */ POINT *pixelLocationRaw);
+
+ /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_PixelLocationRaw )(
+ ICoreWebView2PointerInfo * This,
+ /* [in] */ POINT pixelLocationRaw);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_HimetricLocationRaw )(
+ ICoreWebView2PointerInfo * This,
+ /* [retval][out] */ POINT *himetricLocationRaw);
+
+ /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_HimetricLocationRaw )(
+ ICoreWebView2PointerInfo * This,
+ /* [in] */ POINT himetricLocationRaw);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_Time )(
+ ICoreWebView2PointerInfo * This,
+ /* [retval][out] */ DWORD *time);
+
+ /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_Time )(
+ ICoreWebView2PointerInfo * This,
+ /* [in] */ DWORD time);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_HistoryCount )(
+ ICoreWebView2PointerInfo * This,
+ /* [retval][out] */ UINT32 *historyCount);
+
+ /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_HistoryCount )(
+ ICoreWebView2PointerInfo * This,
+ /* [in] */ UINT32 historyCount);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_InputData )(
+ ICoreWebView2PointerInfo * This,
+ /* [retval][out] */ INT32 *inputData);
+
+ /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_InputData )(
+ ICoreWebView2PointerInfo * This,
+ /* [in] */ INT32 inputData);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_KeyStates )(
+ ICoreWebView2PointerInfo * This,
+ /* [retval][out] */ DWORD *keyStates);
+
+ /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_KeyStates )(
+ ICoreWebView2PointerInfo * This,
+ /* [in] */ DWORD keyStates);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_PerformanceCount )(
+ ICoreWebView2PointerInfo * This,
+ /* [retval][out] */ UINT64 *performanceCount);
+
+ /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_PerformanceCount )(
+ ICoreWebView2PointerInfo * This,
+ /* [in] */ UINT64 performanceCount);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_ButtonChangeKind )(
+ ICoreWebView2PointerInfo * This,
+ /* [retval][out] */ INT32 *buttonChangeKind);
+
+ /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_ButtonChangeKind )(
+ ICoreWebView2PointerInfo * This,
+ /* [in] */ INT32 buttonChangeKind);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_PenFlags )(
+ ICoreWebView2PointerInfo * This,
+ /* [retval][out] */ UINT32 *penFLags);
+
+ /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_PenFlags )(
+ ICoreWebView2PointerInfo * This,
+ /* [in] */ UINT32 penFLags);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_PenMask )(
+ ICoreWebView2PointerInfo * This,
+ /* [retval][out] */ UINT32 *penMask);
+
+ /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_PenMask )(
+ ICoreWebView2PointerInfo * This,
+ /* [in] */ UINT32 penMask);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_PenPressure )(
+ ICoreWebView2PointerInfo * This,
+ /* [retval][out] */ UINT32 *penPressure);
+
+ /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_PenPressure )(
+ ICoreWebView2PointerInfo * This,
+ /* [in] */ UINT32 penPressure);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_PenRotation )(
+ ICoreWebView2PointerInfo * This,
+ /* [retval][out] */ UINT32 *penRotation);
+
+ /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_PenRotation )(
+ ICoreWebView2PointerInfo * This,
+ /* [in] */ UINT32 penRotation);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_PenTiltX )(
+ ICoreWebView2PointerInfo * This,
+ /* [retval][out] */ INT32 *penTiltX);
+
+ /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_PenTiltX )(
+ ICoreWebView2PointerInfo * This,
+ /* [in] */ INT32 penTiltX);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_PenTiltY )(
+ ICoreWebView2PointerInfo * This,
+ /* [retval][out] */ INT32 *penTiltY);
+
+ /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_PenTiltY )(
+ ICoreWebView2PointerInfo * This,
+ /* [in] */ INT32 penTiltY);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_TouchFlags )(
+ ICoreWebView2PointerInfo * This,
+ /* [retval][out] */ UINT32 *touchFlags);
+
+ /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_TouchFlags )(
+ ICoreWebView2PointerInfo * This,
+ /* [in] */ UINT32 touchFlags);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_TouchMask )(
+ ICoreWebView2PointerInfo * This,
+ /* [retval][out] */ UINT32 *touchMask);
+
+ /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_TouchMask )(
+ ICoreWebView2PointerInfo * This,
+ /* [in] */ UINT32 touchMask);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_TouchContact )(
+ ICoreWebView2PointerInfo * This,
+ /* [retval][out] */ RECT *touchContact);
+
+ /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_TouchContact )(
+ ICoreWebView2PointerInfo * This,
+ /* [in] */ RECT touchContact);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_TouchContactRaw )(
+ ICoreWebView2PointerInfo * This,
+ /* [retval][out] */ RECT *touchContactRaw);
+
+ /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_TouchContactRaw )(
+ ICoreWebView2PointerInfo * This,
+ /* [in] */ RECT touchContactRaw);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_TouchOrientation )(
+ ICoreWebView2PointerInfo * This,
+ /* [retval][out] */ UINT32 *touchOrientation);
+
+ /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_TouchOrientation )(
+ ICoreWebView2PointerInfo * This,
+ /* [in] */ UINT32 touchOrientation);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_TouchPressure )(
+ ICoreWebView2PointerInfo * This,
+ /* [retval][out] */ UINT32 *touchPressure);
+
+ /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_TouchPressure )(
+ ICoreWebView2PointerInfo * This,
+ /* [in] */ UINT32 touchPressure);
+
+ END_INTERFACE
+ } ICoreWebView2PointerInfoVtbl;
+
+ interface ICoreWebView2PointerInfo
+ {
+ CONST_VTBL struct ICoreWebView2PointerInfoVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define ICoreWebView2PointerInfo_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define ICoreWebView2PointerInfo_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define ICoreWebView2PointerInfo_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define ICoreWebView2PointerInfo_get_PointerKind(This,pointerKind) \
+ ( (This)->lpVtbl -> get_PointerKind(This,pointerKind) )
+
+#define ICoreWebView2PointerInfo_put_PointerKind(This,pointerKind) \
+ ( (This)->lpVtbl -> put_PointerKind(This,pointerKind) )
+
+#define ICoreWebView2PointerInfo_get_PointerId(This,pointerId) \
+ ( (This)->lpVtbl -> get_PointerId(This,pointerId) )
+
+#define ICoreWebView2PointerInfo_put_PointerId(This,pointerId) \
+ ( (This)->lpVtbl -> put_PointerId(This,pointerId) )
+
+#define ICoreWebView2PointerInfo_get_FrameId(This,frameId) \
+ ( (This)->lpVtbl -> get_FrameId(This,frameId) )
+
+#define ICoreWebView2PointerInfo_put_FrameId(This,frameId) \
+ ( (This)->lpVtbl -> put_FrameId(This,frameId) )
+
+#define ICoreWebView2PointerInfo_get_PointerFlags(This,pointerFlags) \
+ ( (This)->lpVtbl -> get_PointerFlags(This,pointerFlags) )
+
+#define ICoreWebView2PointerInfo_put_PointerFlags(This,pointerFlags) \
+ ( (This)->lpVtbl -> put_PointerFlags(This,pointerFlags) )
+
+#define ICoreWebView2PointerInfo_get_PointerDeviceRect(This,pointerDeviceRect) \
+ ( (This)->lpVtbl -> get_PointerDeviceRect(This,pointerDeviceRect) )
+
+#define ICoreWebView2PointerInfo_put_PointerDeviceRect(This,pointerDeviceRect) \
+ ( (This)->lpVtbl -> put_PointerDeviceRect(This,pointerDeviceRect) )
+
+#define ICoreWebView2PointerInfo_get_DisplayRect(This,displayRect) \
+ ( (This)->lpVtbl -> get_DisplayRect(This,displayRect) )
+
+#define ICoreWebView2PointerInfo_put_DisplayRect(This,displayRect) \
+ ( (This)->lpVtbl -> put_DisplayRect(This,displayRect) )
+
+#define ICoreWebView2PointerInfo_get_PixelLocation(This,pixelLocation) \
+ ( (This)->lpVtbl -> get_PixelLocation(This,pixelLocation) )
+
+#define ICoreWebView2PointerInfo_put_PixelLocation(This,pixelLocation) \
+ ( (This)->lpVtbl -> put_PixelLocation(This,pixelLocation) )
+
+#define ICoreWebView2PointerInfo_get_HimetricLocation(This,himetricLocation) \
+ ( (This)->lpVtbl -> get_HimetricLocation(This,himetricLocation) )
+
+#define ICoreWebView2PointerInfo_put_HimetricLocation(This,himetricLocation) \
+ ( (This)->lpVtbl -> put_HimetricLocation(This,himetricLocation) )
+
+#define ICoreWebView2PointerInfo_get_PixelLocationRaw(This,pixelLocationRaw) \
+ ( (This)->lpVtbl -> get_PixelLocationRaw(This,pixelLocationRaw) )
+
+#define ICoreWebView2PointerInfo_put_PixelLocationRaw(This,pixelLocationRaw) \
+ ( (This)->lpVtbl -> put_PixelLocationRaw(This,pixelLocationRaw) )
+
+#define ICoreWebView2PointerInfo_get_HimetricLocationRaw(This,himetricLocationRaw) \
+ ( (This)->lpVtbl -> get_HimetricLocationRaw(This,himetricLocationRaw) )
+
+#define ICoreWebView2PointerInfo_put_HimetricLocationRaw(This,himetricLocationRaw) \
+ ( (This)->lpVtbl -> put_HimetricLocationRaw(This,himetricLocationRaw) )
+
+#define ICoreWebView2PointerInfo_get_Time(This,time) \
+ ( (This)->lpVtbl -> get_Time(This,time) )
+
+#define ICoreWebView2PointerInfo_put_Time(This,time) \
+ ( (This)->lpVtbl -> put_Time(This,time) )
+
+#define ICoreWebView2PointerInfo_get_HistoryCount(This,historyCount) \
+ ( (This)->lpVtbl -> get_HistoryCount(This,historyCount) )
+
+#define ICoreWebView2PointerInfo_put_HistoryCount(This,historyCount) \
+ ( (This)->lpVtbl -> put_HistoryCount(This,historyCount) )
+
+#define ICoreWebView2PointerInfo_get_InputData(This,inputData) \
+ ( (This)->lpVtbl -> get_InputData(This,inputData) )
+
+#define ICoreWebView2PointerInfo_put_InputData(This,inputData) \
+ ( (This)->lpVtbl -> put_InputData(This,inputData) )
+
+#define ICoreWebView2PointerInfo_get_KeyStates(This,keyStates) \
+ ( (This)->lpVtbl -> get_KeyStates(This,keyStates) )
+
+#define ICoreWebView2PointerInfo_put_KeyStates(This,keyStates) \
+ ( (This)->lpVtbl -> put_KeyStates(This,keyStates) )
+
+#define ICoreWebView2PointerInfo_get_PerformanceCount(This,performanceCount) \
+ ( (This)->lpVtbl -> get_PerformanceCount(This,performanceCount) )
+
+#define ICoreWebView2PointerInfo_put_PerformanceCount(This,performanceCount) \
+ ( (This)->lpVtbl -> put_PerformanceCount(This,performanceCount) )
+
+#define ICoreWebView2PointerInfo_get_ButtonChangeKind(This,buttonChangeKind) \
+ ( (This)->lpVtbl -> get_ButtonChangeKind(This,buttonChangeKind) )
+
+#define ICoreWebView2PointerInfo_put_ButtonChangeKind(This,buttonChangeKind) \
+ ( (This)->lpVtbl -> put_ButtonChangeKind(This,buttonChangeKind) )
+
+#define ICoreWebView2PointerInfo_get_PenFlags(This,penFLags) \
+ ( (This)->lpVtbl -> get_PenFlags(This,penFLags) )
+
+#define ICoreWebView2PointerInfo_put_PenFlags(This,penFLags) \
+ ( (This)->lpVtbl -> put_PenFlags(This,penFLags) )
+
+#define ICoreWebView2PointerInfo_get_PenMask(This,penMask) \
+ ( (This)->lpVtbl -> get_PenMask(This,penMask) )
+
+#define ICoreWebView2PointerInfo_put_PenMask(This,penMask) \
+ ( (This)->lpVtbl -> put_PenMask(This,penMask) )
+
+#define ICoreWebView2PointerInfo_get_PenPressure(This,penPressure) \
+ ( (This)->lpVtbl -> get_PenPressure(This,penPressure) )
+
+#define ICoreWebView2PointerInfo_put_PenPressure(This,penPressure) \
+ ( (This)->lpVtbl -> put_PenPressure(This,penPressure) )
+
+#define ICoreWebView2PointerInfo_get_PenRotation(This,penRotation) \
+ ( (This)->lpVtbl -> get_PenRotation(This,penRotation) )
+
+#define ICoreWebView2PointerInfo_put_PenRotation(This,penRotation) \
+ ( (This)->lpVtbl -> put_PenRotation(This,penRotation) )
+
+#define ICoreWebView2PointerInfo_get_PenTiltX(This,penTiltX) \
+ ( (This)->lpVtbl -> get_PenTiltX(This,penTiltX) )
+
+#define ICoreWebView2PointerInfo_put_PenTiltX(This,penTiltX) \
+ ( (This)->lpVtbl -> put_PenTiltX(This,penTiltX) )
+
+#define ICoreWebView2PointerInfo_get_PenTiltY(This,penTiltY) \
+ ( (This)->lpVtbl -> get_PenTiltY(This,penTiltY) )
+
+#define ICoreWebView2PointerInfo_put_PenTiltY(This,penTiltY) \
+ ( (This)->lpVtbl -> put_PenTiltY(This,penTiltY) )
+
+#define ICoreWebView2PointerInfo_get_TouchFlags(This,touchFlags) \
+ ( (This)->lpVtbl -> get_TouchFlags(This,touchFlags) )
+
+#define ICoreWebView2PointerInfo_put_TouchFlags(This,touchFlags) \
+ ( (This)->lpVtbl -> put_TouchFlags(This,touchFlags) )
+
+#define ICoreWebView2PointerInfo_get_TouchMask(This,touchMask) \
+ ( (This)->lpVtbl -> get_TouchMask(This,touchMask) )
+
+#define ICoreWebView2PointerInfo_put_TouchMask(This,touchMask) \
+ ( (This)->lpVtbl -> put_TouchMask(This,touchMask) )
+
+#define ICoreWebView2PointerInfo_get_TouchContact(This,touchContact) \
+ ( (This)->lpVtbl -> get_TouchContact(This,touchContact) )
+
+#define ICoreWebView2PointerInfo_put_TouchContact(This,touchContact) \
+ ( (This)->lpVtbl -> put_TouchContact(This,touchContact) )
+
+#define ICoreWebView2PointerInfo_get_TouchContactRaw(This,touchContactRaw) \
+ ( (This)->lpVtbl -> get_TouchContactRaw(This,touchContactRaw) )
+
+#define ICoreWebView2PointerInfo_put_TouchContactRaw(This,touchContactRaw) \
+ ( (This)->lpVtbl -> put_TouchContactRaw(This,touchContactRaw) )
+
+#define ICoreWebView2PointerInfo_get_TouchOrientation(This,touchOrientation) \
+ ( (This)->lpVtbl -> get_TouchOrientation(This,touchOrientation) )
+
+#define ICoreWebView2PointerInfo_put_TouchOrientation(This,touchOrientation) \
+ ( (This)->lpVtbl -> put_TouchOrientation(This,touchOrientation) )
+
+#define ICoreWebView2PointerInfo_get_TouchPressure(This,touchPressure) \
+ ( (This)->lpVtbl -> get_TouchPressure(This,touchPressure) )
+
+#define ICoreWebView2PointerInfo_put_TouchPressure(This,touchPressure) \
+ ( (This)->lpVtbl -> put_TouchPressure(This,touchPressure) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __ICoreWebView2PointerInfo_INTERFACE_DEFINED__ */
+
+
+#ifndef __ICoreWebView2ProcessFailedEventArgs_INTERFACE_DEFINED__
+#define __ICoreWebView2ProcessFailedEventArgs_INTERFACE_DEFINED__
+
+/* interface ICoreWebView2ProcessFailedEventArgs */
+/* [unique][object][uuid] */
+
+
+EXTERN_C __declspec(selectany) const IID IID_ICoreWebView2ProcessFailedEventArgs = {0x8155a9a4,0x1474,0x4a86,{0x8c,0xae,0x15,0x1b,0x0f,0xa6,0xb8,0xca}};
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("8155a9a4-1474-4a86-8cae-151b0fa6b8ca")
+ ICoreWebView2ProcessFailedEventArgs : public IUnknown
+ {
+ public:
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_ProcessFailedKind(
+ /* [retval][out] */ COREWEBVIEW2_PROCESS_FAILED_KIND *processFailedKind) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct ICoreWebView2ProcessFailedEventArgsVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ ICoreWebView2ProcessFailedEventArgs * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ ICoreWebView2ProcessFailedEventArgs * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ ICoreWebView2ProcessFailedEventArgs * This);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_ProcessFailedKind )(
+ ICoreWebView2ProcessFailedEventArgs * This,
+ /* [retval][out] */ COREWEBVIEW2_PROCESS_FAILED_KIND *processFailedKind);
+
+ END_INTERFACE
+ } ICoreWebView2ProcessFailedEventArgsVtbl;
+
+ interface ICoreWebView2ProcessFailedEventArgs
+ {
+ CONST_VTBL struct ICoreWebView2ProcessFailedEventArgsVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define ICoreWebView2ProcessFailedEventArgs_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define ICoreWebView2ProcessFailedEventArgs_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define ICoreWebView2ProcessFailedEventArgs_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define ICoreWebView2ProcessFailedEventArgs_get_ProcessFailedKind(This,processFailedKind) \
+ ( (This)->lpVtbl -> get_ProcessFailedKind(This,processFailedKind) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __ICoreWebView2ProcessFailedEventArgs_INTERFACE_DEFINED__ */
+
+
+#ifndef __ICoreWebView2ProcessFailedEventArgs2_INTERFACE_DEFINED__
+#define __ICoreWebView2ProcessFailedEventArgs2_INTERFACE_DEFINED__
+
+/* interface ICoreWebView2ProcessFailedEventArgs2 */
+/* [unique][object][uuid] */
+
+
+EXTERN_C __declspec(selectany) const IID IID_ICoreWebView2ProcessFailedEventArgs2 = {0x4dab9422,0x46fa,0x4c3e,{0xa5,0xd2,0x41,0xd2,0x07,0x1d,0x36,0x80}};
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("4dab9422-46fa-4c3e-a5d2-41d2071d3680")
+ ICoreWebView2ProcessFailedEventArgs2 : public ICoreWebView2ProcessFailedEventArgs
+ {
+ public:
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_Reason(
+ /* [retval][out] */ COREWEBVIEW2_PROCESS_FAILED_REASON *reason) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_ExitCode(
+ /* [retval][out] */ int *exitCode) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_ProcessDescription(
+ /* [retval][out] */ LPWSTR *processDescription) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_FrameInfosForFailedProcess(
+ /* [retval][out] */ ICoreWebView2FrameInfoCollection **frames) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct ICoreWebView2ProcessFailedEventArgs2Vtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ ICoreWebView2ProcessFailedEventArgs2 * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ ICoreWebView2ProcessFailedEventArgs2 * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ ICoreWebView2ProcessFailedEventArgs2 * This);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_ProcessFailedKind )(
+ ICoreWebView2ProcessFailedEventArgs2 * This,
+ /* [retval][out] */ COREWEBVIEW2_PROCESS_FAILED_KIND *processFailedKind);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_Reason )(
+ ICoreWebView2ProcessFailedEventArgs2 * This,
+ /* [retval][out] */ COREWEBVIEW2_PROCESS_FAILED_REASON *reason);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_ExitCode )(
+ ICoreWebView2ProcessFailedEventArgs2 * This,
+ /* [retval][out] */ int *exitCode);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_ProcessDescription )(
+ ICoreWebView2ProcessFailedEventArgs2 * This,
+ /* [retval][out] */ LPWSTR *processDescription);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_FrameInfosForFailedProcess )(
+ ICoreWebView2ProcessFailedEventArgs2 * This,
+ /* [retval][out] */ ICoreWebView2FrameInfoCollection **frames);
+
+ END_INTERFACE
+ } ICoreWebView2ProcessFailedEventArgs2Vtbl;
+
+ interface ICoreWebView2ProcessFailedEventArgs2
+ {
+ CONST_VTBL struct ICoreWebView2ProcessFailedEventArgs2Vtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define ICoreWebView2ProcessFailedEventArgs2_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define ICoreWebView2ProcessFailedEventArgs2_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define ICoreWebView2ProcessFailedEventArgs2_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define ICoreWebView2ProcessFailedEventArgs2_get_ProcessFailedKind(This,processFailedKind) \
+ ( (This)->lpVtbl -> get_ProcessFailedKind(This,processFailedKind) )
+
+
+#define ICoreWebView2ProcessFailedEventArgs2_get_Reason(This,reason) \
+ ( (This)->lpVtbl -> get_Reason(This,reason) )
+
+#define ICoreWebView2ProcessFailedEventArgs2_get_ExitCode(This,exitCode) \
+ ( (This)->lpVtbl -> get_ExitCode(This,exitCode) )
+
+#define ICoreWebView2ProcessFailedEventArgs2_get_ProcessDescription(This,processDescription) \
+ ( (This)->lpVtbl -> get_ProcessDescription(This,processDescription) )
+
+#define ICoreWebView2ProcessFailedEventArgs2_get_FrameInfosForFailedProcess(This,frames) \
+ ( (This)->lpVtbl -> get_FrameInfosForFailedProcess(This,frames) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __ICoreWebView2ProcessFailedEventArgs2_INTERFACE_DEFINED__ */
+
+
+#ifndef __ICoreWebView2ProcessFailedEventHandler_INTERFACE_DEFINED__
+#define __ICoreWebView2ProcessFailedEventHandler_INTERFACE_DEFINED__
+
+/* interface ICoreWebView2ProcessFailedEventHandler */
+/* [unique][object][uuid] */
+
+
+EXTERN_C __declspec(selectany) const IID IID_ICoreWebView2ProcessFailedEventHandler = {0x79e0aea4,0x990b,0x42d9,{0xaa,0x1d,0x0f,0xcc,0x2e,0x5b,0xc7,0xf1}};
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("79e0aea4-990b-42d9-aa1d-0fcc2e5bc7f1")
+ ICoreWebView2ProcessFailedEventHandler : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE Invoke(
+ /* [in] */ ICoreWebView2 *sender,
+ /* [in] */ ICoreWebView2ProcessFailedEventArgs *args) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct ICoreWebView2ProcessFailedEventHandlerVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ ICoreWebView2ProcessFailedEventHandler * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ ICoreWebView2ProcessFailedEventHandler * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ ICoreWebView2ProcessFailedEventHandler * This);
+
+ HRESULT ( STDMETHODCALLTYPE *Invoke )(
+ ICoreWebView2ProcessFailedEventHandler * This,
+ /* [in] */ ICoreWebView2 *sender,
+ /* [in] */ ICoreWebView2ProcessFailedEventArgs *args);
+
+ END_INTERFACE
+ } ICoreWebView2ProcessFailedEventHandlerVtbl;
+
+ interface ICoreWebView2ProcessFailedEventHandler
+ {
+ CONST_VTBL struct ICoreWebView2ProcessFailedEventHandlerVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define ICoreWebView2ProcessFailedEventHandler_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define ICoreWebView2ProcessFailedEventHandler_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define ICoreWebView2ProcessFailedEventHandler_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define ICoreWebView2ProcessFailedEventHandler_Invoke(This,sender,args) \
+ ( (This)->lpVtbl -> Invoke(This,sender,args) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __ICoreWebView2ProcessFailedEventHandler_INTERFACE_DEFINED__ */
+
+
+#ifndef __ICoreWebView2RasterizationScaleChangedEventHandler_INTERFACE_DEFINED__
+#define __ICoreWebView2RasterizationScaleChangedEventHandler_INTERFACE_DEFINED__
+
+/* interface ICoreWebView2RasterizationScaleChangedEventHandler */
+/* [unique][object][uuid] */
+
+
+EXTERN_C __declspec(selectany) const IID IID_ICoreWebView2RasterizationScaleChangedEventHandler = {0x9c98c8b1,0xac53,0x427e,{0xa3,0x45,0x30,0x49,0xb5,0x52,0x4b,0xbe}};
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("9c98c8b1-ac53-427e-a345-3049b5524bbe")
+ ICoreWebView2RasterizationScaleChangedEventHandler : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE Invoke(
+ /* [in] */ ICoreWebView2Controller *sender,
+ /* [in] */ IUnknown *args) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct ICoreWebView2RasterizationScaleChangedEventHandlerVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ ICoreWebView2RasterizationScaleChangedEventHandler * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ ICoreWebView2RasterizationScaleChangedEventHandler * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ ICoreWebView2RasterizationScaleChangedEventHandler * This);
+
+ HRESULT ( STDMETHODCALLTYPE *Invoke )(
+ ICoreWebView2RasterizationScaleChangedEventHandler * This,
+ /* [in] */ ICoreWebView2Controller *sender,
+ /* [in] */ IUnknown *args);
+
+ END_INTERFACE
+ } ICoreWebView2RasterizationScaleChangedEventHandlerVtbl;
+
+ interface ICoreWebView2RasterizationScaleChangedEventHandler
+ {
+ CONST_VTBL struct ICoreWebView2RasterizationScaleChangedEventHandlerVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define ICoreWebView2RasterizationScaleChangedEventHandler_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define ICoreWebView2RasterizationScaleChangedEventHandler_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define ICoreWebView2RasterizationScaleChangedEventHandler_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define ICoreWebView2RasterizationScaleChangedEventHandler_Invoke(This,sender,args) \
+ ( (This)->lpVtbl -> Invoke(This,sender,args) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __ICoreWebView2RasterizationScaleChangedEventHandler_INTERFACE_DEFINED__ */
+
+
+#ifndef __ICoreWebView2ScriptDialogOpeningEventArgs_INTERFACE_DEFINED__
+#define __ICoreWebView2ScriptDialogOpeningEventArgs_INTERFACE_DEFINED__
+
+/* interface ICoreWebView2ScriptDialogOpeningEventArgs */
+/* [unique][object][uuid] */
+
+
+EXTERN_C __declspec(selectany) const IID IID_ICoreWebView2ScriptDialogOpeningEventArgs = {0x7390bb70,0xabe0,0x4843,{0x95,0x29,0xf1,0x43,0xb3,0x1b,0x03,0xd6}};
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("7390bb70-abe0-4843-9529-f143b31b03d6")
+ ICoreWebView2ScriptDialogOpeningEventArgs : public IUnknown
+ {
+ public:
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_Uri(
+ /* [retval][out] */ LPWSTR *uri) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_Kind(
+ /* [retval][out] */ COREWEBVIEW2_SCRIPT_DIALOG_KIND *kind) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_Message(
+ /* [retval][out] */ LPWSTR *message) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE Accept( void) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_DefaultText(
+ /* [retval][out] */ LPWSTR *defaultText) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_ResultText(
+ /* [retval][out] */ LPWSTR *resultText) = 0;
+
+ virtual /* [propput] */ HRESULT STDMETHODCALLTYPE put_ResultText(
+ /* [in] */ LPCWSTR resultText) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetDeferral(
+ /* [retval][out] */ ICoreWebView2Deferral **deferral) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct ICoreWebView2ScriptDialogOpeningEventArgsVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ ICoreWebView2ScriptDialogOpeningEventArgs * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ ICoreWebView2ScriptDialogOpeningEventArgs * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ ICoreWebView2ScriptDialogOpeningEventArgs * This);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_Uri )(
+ ICoreWebView2ScriptDialogOpeningEventArgs * This,
+ /* [retval][out] */ LPWSTR *uri);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_Kind )(
+ ICoreWebView2ScriptDialogOpeningEventArgs * This,
+ /* [retval][out] */ COREWEBVIEW2_SCRIPT_DIALOG_KIND *kind);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_Message )(
+ ICoreWebView2ScriptDialogOpeningEventArgs * This,
+ /* [retval][out] */ LPWSTR *message);
+
+ HRESULT ( STDMETHODCALLTYPE *Accept )(
+ ICoreWebView2ScriptDialogOpeningEventArgs * This);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_DefaultText )(
+ ICoreWebView2ScriptDialogOpeningEventArgs * This,
+ /* [retval][out] */ LPWSTR *defaultText);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_ResultText )(
+ ICoreWebView2ScriptDialogOpeningEventArgs * This,
+ /* [retval][out] */ LPWSTR *resultText);
+
+ /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_ResultText )(
+ ICoreWebView2ScriptDialogOpeningEventArgs * This,
+ /* [in] */ LPCWSTR resultText);
+
+ HRESULT ( STDMETHODCALLTYPE *GetDeferral )(
+ ICoreWebView2ScriptDialogOpeningEventArgs * This,
+ /* [retval][out] */ ICoreWebView2Deferral **deferral);
+
+ END_INTERFACE
+ } ICoreWebView2ScriptDialogOpeningEventArgsVtbl;
+
+ interface ICoreWebView2ScriptDialogOpeningEventArgs
+ {
+ CONST_VTBL struct ICoreWebView2ScriptDialogOpeningEventArgsVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define ICoreWebView2ScriptDialogOpeningEventArgs_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define ICoreWebView2ScriptDialogOpeningEventArgs_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define ICoreWebView2ScriptDialogOpeningEventArgs_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define ICoreWebView2ScriptDialogOpeningEventArgs_get_Uri(This,uri) \
+ ( (This)->lpVtbl -> get_Uri(This,uri) )
+
+#define ICoreWebView2ScriptDialogOpeningEventArgs_get_Kind(This,kind) \
+ ( (This)->lpVtbl -> get_Kind(This,kind) )
+
+#define ICoreWebView2ScriptDialogOpeningEventArgs_get_Message(This,message) \
+ ( (This)->lpVtbl -> get_Message(This,message) )
+
+#define ICoreWebView2ScriptDialogOpeningEventArgs_Accept(This) \
+ ( (This)->lpVtbl -> Accept(This) )
+
+#define ICoreWebView2ScriptDialogOpeningEventArgs_get_DefaultText(This,defaultText) \
+ ( (This)->lpVtbl -> get_DefaultText(This,defaultText) )
+
+#define ICoreWebView2ScriptDialogOpeningEventArgs_get_ResultText(This,resultText) \
+ ( (This)->lpVtbl -> get_ResultText(This,resultText) )
+
+#define ICoreWebView2ScriptDialogOpeningEventArgs_put_ResultText(This,resultText) \
+ ( (This)->lpVtbl -> put_ResultText(This,resultText) )
+
+#define ICoreWebView2ScriptDialogOpeningEventArgs_GetDeferral(This,deferral) \
+ ( (This)->lpVtbl -> GetDeferral(This,deferral) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __ICoreWebView2ScriptDialogOpeningEventArgs_INTERFACE_DEFINED__ */
+
+
+#ifndef __ICoreWebView2ScriptDialogOpeningEventHandler_INTERFACE_DEFINED__
+#define __ICoreWebView2ScriptDialogOpeningEventHandler_INTERFACE_DEFINED__
+
+/* interface ICoreWebView2ScriptDialogOpeningEventHandler */
+/* [unique][object][uuid] */
+
+
+EXTERN_C __declspec(selectany) const IID IID_ICoreWebView2ScriptDialogOpeningEventHandler = {0xef381bf9,0xafa8,0x4e37,{0x91,0xc4,0x8a,0xc4,0x85,0x24,0xbd,0xfb}};
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("ef381bf9-afa8-4e37-91c4-8ac48524bdfb")
+ ICoreWebView2ScriptDialogOpeningEventHandler : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE Invoke(
+ /* [in] */ ICoreWebView2 *sender,
+ /* [in] */ ICoreWebView2ScriptDialogOpeningEventArgs *args) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct ICoreWebView2ScriptDialogOpeningEventHandlerVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ ICoreWebView2ScriptDialogOpeningEventHandler * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ ICoreWebView2ScriptDialogOpeningEventHandler * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ ICoreWebView2ScriptDialogOpeningEventHandler * This);
+
+ HRESULT ( STDMETHODCALLTYPE *Invoke )(
+ ICoreWebView2ScriptDialogOpeningEventHandler * This,
+ /* [in] */ ICoreWebView2 *sender,
+ /* [in] */ ICoreWebView2ScriptDialogOpeningEventArgs *args);
+
+ END_INTERFACE
+ } ICoreWebView2ScriptDialogOpeningEventHandlerVtbl;
+
+ interface ICoreWebView2ScriptDialogOpeningEventHandler
+ {
+ CONST_VTBL struct ICoreWebView2ScriptDialogOpeningEventHandlerVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define ICoreWebView2ScriptDialogOpeningEventHandler_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define ICoreWebView2ScriptDialogOpeningEventHandler_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define ICoreWebView2ScriptDialogOpeningEventHandler_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define ICoreWebView2ScriptDialogOpeningEventHandler_Invoke(This,sender,args) \
+ ( (This)->lpVtbl -> Invoke(This,sender,args) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __ICoreWebView2ScriptDialogOpeningEventHandler_INTERFACE_DEFINED__ */
+
+
+#ifndef __ICoreWebView2Settings_INTERFACE_DEFINED__
+#define __ICoreWebView2Settings_INTERFACE_DEFINED__
+
+/* interface ICoreWebView2Settings */
+/* [unique][object][uuid] */
+
+
+EXTERN_C __declspec(selectany) const IID IID_ICoreWebView2Settings = {0xe562e4f0,0xd7fa,0x43ac,{0x8d,0x71,0xc0,0x51,0x50,0x49,0x9f,0x00}};
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("e562e4f0-d7fa-43ac-8d71-c05150499f00")
+ ICoreWebView2Settings : public IUnknown
+ {
+ public:
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_IsScriptEnabled(
+ /* [retval][out] */ BOOL *isScriptEnabled) = 0;
+
+ virtual /* [propput] */ HRESULT STDMETHODCALLTYPE put_IsScriptEnabled(
+ /* [in] */ BOOL isScriptEnabled) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_IsWebMessageEnabled(
+ /* [retval][out] */ BOOL *isWebMessageEnabled) = 0;
+
+ virtual /* [propput] */ HRESULT STDMETHODCALLTYPE put_IsWebMessageEnabled(
+ /* [in] */ BOOL isWebMessageEnabled) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_AreDefaultScriptDialogsEnabled(
+ /* [retval][out] */ BOOL *areDefaultScriptDialogsEnabled) = 0;
+
+ virtual /* [propput] */ HRESULT STDMETHODCALLTYPE put_AreDefaultScriptDialogsEnabled(
+ /* [in] */ BOOL areDefaultScriptDialogsEnabled) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_IsStatusBarEnabled(
+ /* [retval][out] */ BOOL *isStatusBarEnabled) = 0;
+
+ virtual /* [propput] */ HRESULT STDMETHODCALLTYPE put_IsStatusBarEnabled(
+ /* [in] */ BOOL isStatusBarEnabled) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_AreDevToolsEnabled(
+ /* [retval][out] */ BOOL *areDevToolsEnabled) = 0;
+
+ virtual /* [propput] */ HRESULT STDMETHODCALLTYPE put_AreDevToolsEnabled(
+ /* [in] */ BOOL areDevToolsEnabled) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_AreDefaultContextMenusEnabled(
+ /* [retval][out] */ BOOL *enabled) = 0;
+
+ virtual /* [propput] */ HRESULT STDMETHODCALLTYPE put_AreDefaultContextMenusEnabled(
+ /* [in] */ BOOL enabled) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_AreHostObjectsAllowed(
+ /* [retval][out] */ BOOL *allowed) = 0;
+
+ virtual /* [propput] */ HRESULT STDMETHODCALLTYPE put_AreHostObjectsAllowed(
+ /* [in] */ BOOL allowed) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_IsZoomControlEnabled(
+ /* [retval][out] */ BOOL *enabled) = 0;
+
+ virtual /* [propput] */ HRESULT STDMETHODCALLTYPE put_IsZoomControlEnabled(
+ /* [in] */ BOOL enabled) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_IsBuiltInErrorPageEnabled(
+ /* [retval][out] */ BOOL *enabled) = 0;
+
+ virtual /* [propput] */ HRESULT STDMETHODCALLTYPE put_IsBuiltInErrorPageEnabled(
+ /* [in] */ BOOL enabled) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct ICoreWebView2SettingsVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ ICoreWebView2Settings * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ ICoreWebView2Settings * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ ICoreWebView2Settings * This);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_IsScriptEnabled )(
+ ICoreWebView2Settings * This,
+ /* [retval][out] */ BOOL *isScriptEnabled);
+
+ /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_IsScriptEnabled )(
+ ICoreWebView2Settings * This,
+ /* [in] */ BOOL isScriptEnabled);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_IsWebMessageEnabled )(
+ ICoreWebView2Settings * This,
+ /* [retval][out] */ BOOL *isWebMessageEnabled);
+
+ /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_IsWebMessageEnabled )(
+ ICoreWebView2Settings * This,
+ /* [in] */ BOOL isWebMessageEnabled);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_AreDefaultScriptDialogsEnabled )(
+ ICoreWebView2Settings * This,
+ /* [retval][out] */ BOOL *areDefaultScriptDialogsEnabled);
+
+ /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_AreDefaultScriptDialogsEnabled )(
+ ICoreWebView2Settings * This,
+ /* [in] */ BOOL areDefaultScriptDialogsEnabled);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_IsStatusBarEnabled )(
+ ICoreWebView2Settings * This,
+ /* [retval][out] */ BOOL *isStatusBarEnabled);
+
+ /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_IsStatusBarEnabled )(
+ ICoreWebView2Settings * This,
+ /* [in] */ BOOL isStatusBarEnabled);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_AreDevToolsEnabled )(
+ ICoreWebView2Settings * This,
+ /* [retval][out] */ BOOL *areDevToolsEnabled);
+
+ /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_AreDevToolsEnabled )(
+ ICoreWebView2Settings * This,
+ /* [in] */ BOOL areDevToolsEnabled);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_AreDefaultContextMenusEnabled )(
+ ICoreWebView2Settings * This,
+ /* [retval][out] */ BOOL *enabled);
+
+ /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_AreDefaultContextMenusEnabled )(
+ ICoreWebView2Settings * This,
+ /* [in] */ BOOL enabled);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_AreHostObjectsAllowed )(
+ ICoreWebView2Settings * This,
+ /* [retval][out] */ BOOL *allowed);
+
+ /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_AreHostObjectsAllowed )(
+ ICoreWebView2Settings * This,
+ /* [in] */ BOOL allowed);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_IsZoomControlEnabled )(
+ ICoreWebView2Settings * This,
+ /* [retval][out] */ BOOL *enabled);
+
+ /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_IsZoomControlEnabled )(
+ ICoreWebView2Settings * This,
+ /* [in] */ BOOL enabled);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_IsBuiltInErrorPageEnabled )(
+ ICoreWebView2Settings * This,
+ /* [retval][out] */ BOOL *enabled);
+
+ /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_IsBuiltInErrorPageEnabled )(
+ ICoreWebView2Settings * This,
+ /* [in] */ BOOL enabled);
+
+ END_INTERFACE
+ } ICoreWebView2SettingsVtbl;
+
+ interface ICoreWebView2Settings
+ {
+ CONST_VTBL struct ICoreWebView2SettingsVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define ICoreWebView2Settings_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define ICoreWebView2Settings_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define ICoreWebView2Settings_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define ICoreWebView2Settings_get_IsScriptEnabled(This,isScriptEnabled) \
+ ( (This)->lpVtbl -> get_IsScriptEnabled(This,isScriptEnabled) )
+
+#define ICoreWebView2Settings_put_IsScriptEnabled(This,isScriptEnabled) \
+ ( (This)->lpVtbl -> put_IsScriptEnabled(This,isScriptEnabled) )
+
+#define ICoreWebView2Settings_get_IsWebMessageEnabled(This,isWebMessageEnabled) \
+ ( (This)->lpVtbl -> get_IsWebMessageEnabled(This,isWebMessageEnabled) )
+
+#define ICoreWebView2Settings_put_IsWebMessageEnabled(This,isWebMessageEnabled) \
+ ( (This)->lpVtbl -> put_IsWebMessageEnabled(This,isWebMessageEnabled) )
+
+#define ICoreWebView2Settings_get_AreDefaultScriptDialogsEnabled(This,areDefaultScriptDialogsEnabled) \
+ ( (This)->lpVtbl -> get_AreDefaultScriptDialogsEnabled(This,areDefaultScriptDialogsEnabled) )
+
+#define ICoreWebView2Settings_put_AreDefaultScriptDialogsEnabled(This,areDefaultScriptDialogsEnabled) \
+ ( (This)->lpVtbl -> put_AreDefaultScriptDialogsEnabled(This,areDefaultScriptDialogsEnabled) )
+
+#define ICoreWebView2Settings_get_IsStatusBarEnabled(This,isStatusBarEnabled) \
+ ( (This)->lpVtbl -> get_IsStatusBarEnabled(This,isStatusBarEnabled) )
+
+#define ICoreWebView2Settings_put_IsStatusBarEnabled(This,isStatusBarEnabled) \
+ ( (This)->lpVtbl -> put_IsStatusBarEnabled(This,isStatusBarEnabled) )
+
+#define ICoreWebView2Settings_get_AreDevToolsEnabled(This,areDevToolsEnabled) \
+ ( (This)->lpVtbl -> get_AreDevToolsEnabled(This,areDevToolsEnabled) )
+
+#define ICoreWebView2Settings_put_AreDevToolsEnabled(This,areDevToolsEnabled) \
+ ( (This)->lpVtbl -> put_AreDevToolsEnabled(This,areDevToolsEnabled) )
+
+#define ICoreWebView2Settings_get_AreDefaultContextMenusEnabled(This,enabled) \
+ ( (This)->lpVtbl -> get_AreDefaultContextMenusEnabled(This,enabled) )
+
+#define ICoreWebView2Settings_put_AreDefaultContextMenusEnabled(This,enabled) \
+ ( (This)->lpVtbl -> put_AreDefaultContextMenusEnabled(This,enabled) )
+
+#define ICoreWebView2Settings_get_AreHostObjectsAllowed(This,allowed) \
+ ( (This)->lpVtbl -> get_AreHostObjectsAllowed(This,allowed) )
+
+#define ICoreWebView2Settings_put_AreHostObjectsAllowed(This,allowed) \
+ ( (This)->lpVtbl -> put_AreHostObjectsAllowed(This,allowed) )
+
+#define ICoreWebView2Settings_get_IsZoomControlEnabled(This,enabled) \
+ ( (This)->lpVtbl -> get_IsZoomControlEnabled(This,enabled) )
+
+#define ICoreWebView2Settings_put_IsZoomControlEnabled(This,enabled) \
+ ( (This)->lpVtbl -> put_IsZoomControlEnabled(This,enabled) )
+
+#define ICoreWebView2Settings_get_IsBuiltInErrorPageEnabled(This,enabled) \
+ ( (This)->lpVtbl -> get_IsBuiltInErrorPageEnabled(This,enabled) )
+
+#define ICoreWebView2Settings_put_IsBuiltInErrorPageEnabled(This,enabled) \
+ ( (This)->lpVtbl -> put_IsBuiltInErrorPageEnabled(This,enabled) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __ICoreWebView2Settings_INTERFACE_DEFINED__ */
+
+
+#ifndef __ICoreWebView2Settings2_INTERFACE_DEFINED__
+#define __ICoreWebView2Settings2_INTERFACE_DEFINED__
+
+/* interface ICoreWebView2Settings2 */
+/* [unique][object][uuid] */
+
+
+EXTERN_C __declspec(selectany) const IID IID_ICoreWebView2Settings2 = {0xee9a0f68,0xf46c,0x4e32,{0xac,0x23,0xef,0x8c,0xac,0x22,0x4d,0x2a}};
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("ee9a0f68-f46c-4e32-ac23-ef8cac224d2a")
+ ICoreWebView2Settings2 : public ICoreWebView2Settings
+ {
+ public:
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_UserAgent(
+ /* [retval][out] */ LPWSTR *userAgent) = 0;
+
+ virtual /* [propput] */ HRESULT STDMETHODCALLTYPE put_UserAgent(
+ /* [in] */ LPCWSTR userAgent) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct ICoreWebView2Settings2Vtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ ICoreWebView2Settings2 * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ ICoreWebView2Settings2 * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ ICoreWebView2Settings2 * This);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_IsScriptEnabled )(
+ ICoreWebView2Settings2 * This,
+ /* [retval][out] */ BOOL *isScriptEnabled);
+
+ /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_IsScriptEnabled )(
+ ICoreWebView2Settings2 * This,
+ /* [in] */ BOOL isScriptEnabled);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_IsWebMessageEnabled )(
+ ICoreWebView2Settings2 * This,
+ /* [retval][out] */ BOOL *isWebMessageEnabled);
+
+ /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_IsWebMessageEnabled )(
+ ICoreWebView2Settings2 * This,
+ /* [in] */ BOOL isWebMessageEnabled);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_AreDefaultScriptDialogsEnabled )(
+ ICoreWebView2Settings2 * This,
+ /* [retval][out] */ BOOL *areDefaultScriptDialogsEnabled);
+
+ /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_AreDefaultScriptDialogsEnabled )(
+ ICoreWebView2Settings2 * This,
+ /* [in] */ BOOL areDefaultScriptDialogsEnabled);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_IsStatusBarEnabled )(
+ ICoreWebView2Settings2 * This,
+ /* [retval][out] */ BOOL *isStatusBarEnabled);
+
+ /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_IsStatusBarEnabled )(
+ ICoreWebView2Settings2 * This,
+ /* [in] */ BOOL isStatusBarEnabled);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_AreDevToolsEnabled )(
+ ICoreWebView2Settings2 * This,
+ /* [retval][out] */ BOOL *areDevToolsEnabled);
+
+ /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_AreDevToolsEnabled )(
+ ICoreWebView2Settings2 * This,
+ /* [in] */ BOOL areDevToolsEnabled);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_AreDefaultContextMenusEnabled )(
+ ICoreWebView2Settings2 * This,
+ /* [retval][out] */ BOOL *enabled);
+
+ /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_AreDefaultContextMenusEnabled )(
+ ICoreWebView2Settings2 * This,
+ /* [in] */ BOOL enabled);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_AreHostObjectsAllowed )(
+ ICoreWebView2Settings2 * This,
+ /* [retval][out] */ BOOL *allowed);
+
+ /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_AreHostObjectsAllowed )(
+ ICoreWebView2Settings2 * This,
+ /* [in] */ BOOL allowed);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_IsZoomControlEnabled )(
+ ICoreWebView2Settings2 * This,
+ /* [retval][out] */ BOOL *enabled);
+
+ /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_IsZoomControlEnabled )(
+ ICoreWebView2Settings2 * This,
+ /* [in] */ BOOL enabled);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_IsBuiltInErrorPageEnabled )(
+ ICoreWebView2Settings2 * This,
+ /* [retval][out] */ BOOL *enabled);
+
+ /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_IsBuiltInErrorPageEnabled )(
+ ICoreWebView2Settings2 * This,
+ /* [in] */ BOOL enabled);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_UserAgent )(
+ ICoreWebView2Settings2 * This,
+ /* [retval][out] */ LPWSTR *userAgent);
+
+ /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_UserAgent )(
+ ICoreWebView2Settings2 * This,
+ /* [in] */ LPCWSTR userAgent);
+
+ END_INTERFACE
+ } ICoreWebView2Settings2Vtbl;
+
+ interface ICoreWebView2Settings2
+ {
+ CONST_VTBL struct ICoreWebView2Settings2Vtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define ICoreWebView2Settings2_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define ICoreWebView2Settings2_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define ICoreWebView2Settings2_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define ICoreWebView2Settings2_get_IsScriptEnabled(This,isScriptEnabled) \
+ ( (This)->lpVtbl -> get_IsScriptEnabled(This,isScriptEnabled) )
+
+#define ICoreWebView2Settings2_put_IsScriptEnabled(This,isScriptEnabled) \
+ ( (This)->lpVtbl -> put_IsScriptEnabled(This,isScriptEnabled) )
+
+#define ICoreWebView2Settings2_get_IsWebMessageEnabled(This,isWebMessageEnabled) \
+ ( (This)->lpVtbl -> get_IsWebMessageEnabled(This,isWebMessageEnabled) )
+
+#define ICoreWebView2Settings2_put_IsWebMessageEnabled(This,isWebMessageEnabled) \
+ ( (This)->lpVtbl -> put_IsWebMessageEnabled(This,isWebMessageEnabled) )
+
+#define ICoreWebView2Settings2_get_AreDefaultScriptDialogsEnabled(This,areDefaultScriptDialogsEnabled) \
+ ( (This)->lpVtbl -> get_AreDefaultScriptDialogsEnabled(This,areDefaultScriptDialogsEnabled) )
+
+#define ICoreWebView2Settings2_put_AreDefaultScriptDialogsEnabled(This,areDefaultScriptDialogsEnabled) \
+ ( (This)->lpVtbl -> put_AreDefaultScriptDialogsEnabled(This,areDefaultScriptDialogsEnabled) )
+
+#define ICoreWebView2Settings2_get_IsStatusBarEnabled(This,isStatusBarEnabled) \
+ ( (This)->lpVtbl -> get_IsStatusBarEnabled(This,isStatusBarEnabled) )
+
+#define ICoreWebView2Settings2_put_IsStatusBarEnabled(This,isStatusBarEnabled) \
+ ( (This)->lpVtbl -> put_IsStatusBarEnabled(This,isStatusBarEnabled) )
+
+#define ICoreWebView2Settings2_get_AreDevToolsEnabled(This,areDevToolsEnabled) \
+ ( (This)->lpVtbl -> get_AreDevToolsEnabled(This,areDevToolsEnabled) )
+
+#define ICoreWebView2Settings2_put_AreDevToolsEnabled(This,areDevToolsEnabled) \
+ ( (This)->lpVtbl -> put_AreDevToolsEnabled(This,areDevToolsEnabled) )
+
+#define ICoreWebView2Settings2_get_AreDefaultContextMenusEnabled(This,enabled) \
+ ( (This)->lpVtbl -> get_AreDefaultContextMenusEnabled(This,enabled) )
+
+#define ICoreWebView2Settings2_put_AreDefaultContextMenusEnabled(This,enabled) \
+ ( (This)->lpVtbl -> put_AreDefaultContextMenusEnabled(This,enabled) )
+
+#define ICoreWebView2Settings2_get_AreHostObjectsAllowed(This,allowed) \
+ ( (This)->lpVtbl -> get_AreHostObjectsAllowed(This,allowed) )
+
+#define ICoreWebView2Settings2_put_AreHostObjectsAllowed(This,allowed) \
+ ( (This)->lpVtbl -> put_AreHostObjectsAllowed(This,allowed) )
+
+#define ICoreWebView2Settings2_get_IsZoomControlEnabled(This,enabled) \
+ ( (This)->lpVtbl -> get_IsZoomControlEnabled(This,enabled) )
+
+#define ICoreWebView2Settings2_put_IsZoomControlEnabled(This,enabled) \
+ ( (This)->lpVtbl -> put_IsZoomControlEnabled(This,enabled) )
+
+#define ICoreWebView2Settings2_get_IsBuiltInErrorPageEnabled(This,enabled) \
+ ( (This)->lpVtbl -> get_IsBuiltInErrorPageEnabled(This,enabled) )
+
+#define ICoreWebView2Settings2_put_IsBuiltInErrorPageEnabled(This,enabled) \
+ ( (This)->lpVtbl -> put_IsBuiltInErrorPageEnabled(This,enabled) )
+
+
+#define ICoreWebView2Settings2_get_UserAgent(This,userAgent) \
+ ( (This)->lpVtbl -> get_UserAgent(This,userAgent) )
+
+#define ICoreWebView2Settings2_put_UserAgent(This,userAgent) \
+ ( (This)->lpVtbl -> put_UserAgent(This,userAgent) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __ICoreWebView2Settings2_INTERFACE_DEFINED__ */
+
+
+#ifndef __ICoreWebView2Settings3_INTERFACE_DEFINED__
+#define __ICoreWebView2Settings3_INTERFACE_DEFINED__
+
+/* interface ICoreWebView2Settings3 */
+/* [unique][object][uuid] */
+
+
+EXTERN_C __declspec(selectany) const IID IID_ICoreWebView2Settings3 = {0xfdb5ab74,0xaf33,0x4854,{0x84,0xf0,0x0a,0x63,0x1d,0xeb,0x5e,0xba}};
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("fdb5ab74-af33-4854-84f0-0a631deb5eba")
+ ICoreWebView2Settings3 : public ICoreWebView2Settings2
+ {
+ public:
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_AreBrowserAcceleratorKeysEnabled(
+ /* [retval][out] */ BOOL *areBrowserAcceleratorKeysEnabled) = 0;
+
+ virtual /* [propput] */ HRESULT STDMETHODCALLTYPE put_AreBrowserAcceleratorKeysEnabled(
+ /* [in] */ BOOL areBrowserAcceleratorKeysEnabled) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct ICoreWebView2Settings3Vtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ ICoreWebView2Settings3 * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ ICoreWebView2Settings3 * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ ICoreWebView2Settings3 * This);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_IsScriptEnabled )(
+ ICoreWebView2Settings3 * This,
+ /* [retval][out] */ BOOL *isScriptEnabled);
+
+ /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_IsScriptEnabled )(
+ ICoreWebView2Settings3 * This,
+ /* [in] */ BOOL isScriptEnabled);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_IsWebMessageEnabled )(
+ ICoreWebView2Settings3 * This,
+ /* [retval][out] */ BOOL *isWebMessageEnabled);
+
+ /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_IsWebMessageEnabled )(
+ ICoreWebView2Settings3 * This,
+ /* [in] */ BOOL isWebMessageEnabled);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_AreDefaultScriptDialogsEnabled )(
+ ICoreWebView2Settings3 * This,
+ /* [retval][out] */ BOOL *areDefaultScriptDialogsEnabled);
+
+ /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_AreDefaultScriptDialogsEnabled )(
+ ICoreWebView2Settings3 * This,
+ /* [in] */ BOOL areDefaultScriptDialogsEnabled);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_IsStatusBarEnabled )(
+ ICoreWebView2Settings3 * This,
+ /* [retval][out] */ BOOL *isStatusBarEnabled);
+
+ /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_IsStatusBarEnabled )(
+ ICoreWebView2Settings3 * This,
+ /* [in] */ BOOL isStatusBarEnabled);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_AreDevToolsEnabled )(
+ ICoreWebView2Settings3 * This,
+ /* [retval][out] */ BOOL *areDevToolsEnabled);
+
+ /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_AreDevToolsEnabled )(
+ ICoreWebView2Settings3 * This,
+ /* [in] */ BOOL areDevToolsEnabled);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_AreDefaultContextMenusEnabled )(
+ ICoreWebView2Settings3 * This,
+ /* [retval][out] */ BOOL *enabled);
+
+ /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_AreDefaultContextMenusEnabled )(
+ ICoreWebView2Settings3 * This,
+ /* [in] */ BOOL enabled);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_AreHostObjectsAllowed )(
+ ICoreWebView2Settings3 * This,
+ /* [retval][out] */ BOOL *allowed);
+
+ /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_AreHostObjectsAllowed )(
+ ICoreWebView2Settings3 * This,
+ /* [in] */ BOOL allowed);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_IsZoomControlEnabled )(
+ ICoreWebView2Settings3 * This,
+ /* [retval][out] */ BOOL *enabled);
+
+ /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_IsZoomControlEnabled )(
+ ICoreWebView2Settings3 * This,
+ /* [in] */ BOOL enabled);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_IsBuiltInErrorPageEnabled )(
+ ICoreWebView2Settings3 * This,
+ /* [retval][out] */ BOOL *enabled);
+
+ /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_IsBuiltInErrorPageEnabled )(
+ ICoreWebView2Settings3 * This,
+ /* [in] */ BOOL enabled);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_UserAgent )(
+ ICoreWebView2Settings3 * This,
+ /* [retval][out] */ LPWSTR *userAgent);
+
+ /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_UserAgent )(
+ ICoreWebView2Settings3 * This,
+ /* [in] */ LPCWSTR userAgent);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_AreBrowserAcceleratorKeysEnabled )(
+ ICoreWebView2Settings3 * This,
+ /* [retval][out] */ BOOL *areBrowserAcceleratorKeysEnabled);
+
+ /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_AreBrowserAcceleratorKeysEnabled )(
+ ICoreWebView2Settings3 * This,
+ /* [in] */ BOOL areBrowserAcceleratorKeysEnabled);
+
+ END_INTERFACE
+ } ICoreWebView2Settings3Vtbl;
+
+ interface ICoreWebView2Settings3
+ {
+ CONST_VTBL struct ICoreWebView2Settings3Vtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define ICoreWebView2Settings3_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define ICoreWebView2Settings3_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define ICoreWebView2Settings3_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define ICoreWebView2Settings3_get_IsScriptEnabled(This,isScriptEnabled) \
+ ( (This)->lpVtbl -> get_IsScriptEnabled(This,isScriptEnabled) )
+
+#define ICoreWebView2Settings3_put_IsScriptEnabled(This,isScriptEnabled) \
+ ( (This)->lpVtbl -> put_IsScriptEnabled(This,isScriptEnabled) )
+
+#define ICoreWebView2Settings3_get_IsWebMessageEnabled(This,isWebMessageEnabled) \
+ ( (This)->lpVtbl -> get_IsWebMessageEnabled(This,isWebMessageEnabled) )
+
+#define ICoreWebView2Settings3_put_IsWebMessageEnabled(This,isWebMessageEnabled) \
+ ( (This)->lpVtbl -> put_IsWebMessageEnabled(This,isWebMessageEnabled) )
+
+#define ICoreWebView2Settings3_get_AreDefaultScriptDialogsEnabled(This,areDefaultScriptDialogsEnabled) \
+ ( (This)->lpVtbl -> get_AreDefaultScriptDialogsEnabled(This,areDefaultScriptDialogsEnabled) )
+
+#define ICoreWebView2Settings3_put_AreDefaultScriptDialogsEnabled(This,areDefaultScriptDialogsEnabled) \
+ ( (This)->lpVtbl -> put_AreDefaultScriptDialogsEnabled(This,areDefaultScriptDialogsEnabled) )
+
+#define ICoreWebView2Settings3_get_IsStatusBarEnabled(This,isStatusBarEnabled) \
+ ( (This)->lpVtbl -> get_IsStatusBarEnabled(This,isStatusBarEnabled) )
+
+#define ICoreWebView2Settings3_put_IsStatusBarEnabled(This,isStatusBarEnabled) \
+ ( (This)->lpVtbl -> put_IsStatusBarEnabled(This,isStatusBarEnabled) )
+
+#define ICoreWebView2Settings3_get_AreDevToolsEnabled(This,areDevToolsEnabled) \
+ ( (This)->lpVtbl -> get_AreDevToolsEnabled(This,areDevToolsEnabled) )
+
+#define ICoreWebView2Settings3_put_AreDevToolsEnabled(This,areDevToolsEnabled) \
+ ( (This)->lpVtbl -> put_AreDevToolsEnabled(This,areDevToolsEnabled) )
+
+#define ICoreWebView2Settings3_get_AreDefaultContextMenusEnabled(This,enabled) \
+ ( (This)->lpVtbl -> get_AreDefaultContextMenusEnabled(This,enabled) )
+
+#define ICoreWebView2Settings3_put_AreDefaultContextMenusEnabled(This,enabled) \
+ ( (This)->lpVtbl -> put_AreDefaultContextMenusEnabled(This,enabled) )
+
+#define ICoreWebView2Settings3_get_AreHostObjectsAllowed(This,allowed) \
+ ( (This)->lpVtbl -> get_AreHostObjectsAllowed(This,allowed) )
+
+#define ICoreWebView2Settings3_put_AreHostObjectsAllowed(This,allowed) \
+ ( (This)->lpVtbl -> put_AreHostObjectsAllowed(This,allowed) )
+
+#define ICoreWebView2Settings3_get_IsZoomControlEnabled(This,enabled) \
+ ( (This)->lpVtbl -> get_IsZoomControlEnabled(This,enabled) )
+
+#define ICoreWebView2Settings3_put_IsZoomControlEnabled(This,enabled) \
+ ( (This)->lpVtbl -> put_IsZoomControlEnabled(This,enabled) )
+
+#define ICoreWebView2Settings3_get_IsBuiltInErrorPageEnabled(This,enabled) \
+ ( (This)->lpVtbl -> get_IsBuiltInErrorPageEnabled(This,enabled) )
+
+#define ICoreWebView2Settings3_put_IsBuiltInErrorPageEnabled(This,enabled) \
+ ( (This)->lpVtbl -> put_IsBuiltInErrorPageEnabled(This,enabled) )
+
+
+#define ICoreWebView2Settings3_get_UserAgent(This,userAgent) \
+ ( (This)->lpVtbl -> get_UserAgent(This,userAgent) )
+
+#define ICoreWebView2Settings3_put_UserAgent(This,userAgent) \
+ ( (This)->lpVtbl -> put_UserAgent(This,userAgent) )
+
+
+#define ICoreWebView2Settings3_get_AreBrowserAcceleratorKeysEnabled(This,areBrowserAcceleratorKeysEnabled) \
+ ( (This)->lpVtbl -> get_AreBrowserAcceleratorKeysEnabled(This,areBrowserAcceleratorKeysEnabled) )
+
+#define ICoreWebView2Settings3_put_AreBrowserAcceleratorKeysEnabled(This,areBrowserAcceleratorKeysEnabled) \
+ ( (This)->lpVtbl -> put_AreBrowserAcceleratorKeysEnabled(This,areBrowserAcceleratorKeysEnabled) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __ICoreWebView2Settings3_INTERFACE_DEFINED__ */
+
+
+#ifndef __ICoreWebView2SourceChangedEventArgs_INTERFACE_DEFINED__
+#define __ICoreWebView2SourceChangedEventArgs_INTERFACE_DEFINED__
+
+/* interface ICoreWebView2SourceChangedEventArgs */
+/* [unique][object][uuid] */
+
+
+EXTERN_C __declspec(selectany) const IID IID_ICoreWebView2SourceChangedEventArgs = {0x31e0e545,0x1dba,0x4266,{0x89,0x14,0xf6,0x38,0x48,0xa1,0xf7,0xd7}};
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("31e0e545-1dba-4266-8914-f63848a1f7d7")
+ ICoreWebView2SourceChangedEventArgs : public IUnknown
+ {
+ public:
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_IsNewDocument(
+ /* [retval][out] */ BOOL *isNewDocument) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct ICoreWebView2SourceChangedEventArgsVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ ICoreWebView2SourceChangedEventArgs * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ ICoreWebView2SourceChangedEventArgs * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ ICoreWebView2SourceChangedEventArgs * This);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_IsNewDocument )(
+ ICoreWebView2SourceChangedEventArgs * This,
+ /* [retval][out] */ BOOL *isNewDocument);
+
+ END_INTERFACE
+ } ICoreWebView2SourceChangedEventArgsVtbl;
+
+ interface ICoreWebView2SourceChangedEventArgs
+ {
+ CONST_VTBL struct ICoreWebView2SourceChangedEventArgsVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define ICoreWebView2SourceChangedEventArgs_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define ICoreWebView2SourceChangedEventArgs_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define ICoreWebView2SourceChangedEventArgs_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define ICoreWebView2SourceChangedEventArgs_get_IsNewDocument(This,isNewDocument) \
+ ( (This)->lpVtbl -> get_IsNewDocument(This,isNewDocument) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __ICoreWebView2SourceChangedEventArgs_INTERFACE_DEFINED__ */
+
+
+#ifndef __ICoreWebView2SourceChangedEventHandler_INTERFACE_DEFINED__
+#define __ICoreWebView2SourceChangedEventHandler_INTERFACE_DEFINED__
+
+/* interface ICoreWebView2SourceChangedEventHandler */
+/* [unique][object][uuid] */
+
+
+EXTERN_C __declspec(selectany) const IID IID_ICoreWebView2SourceChangedEventHandler = {0x3c067f9f,0x5388,0x4772,{0x8b,0x48,0x79,0xf7,0xef,0x1a,0xb3,0x7c}};
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("3c067f9f-5388-4772-8b48-79f7ef1ab37c")
+ ICoreWebView2SourceChangedEventHandler : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE Invoke(
+ /* [in] */ ICoreWebView2 *sender,
+ /* [in] */ ICoreWebView2SourceChangedEventArgs *args) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct ICoreWebView2SourceChangedEventHandlerVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ ICoreWebView2SourceChangedEventHandler * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ ICoreWebView2SourceChangedEventHandler * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ ICoreWebView2SourceChangedEventHandler * This);
+
+ HRESULT ( STDMETHODCALLTYPE *Invoke )(
+ ICoreWebView2SourceChangedEventHandler * This,
+ /* [in] */ ICoreWebView2 *sender,
+ /* [in] */ ICoreWebView2SourceChangedEventArgs *args);
+
+ END_INTERFACE
+ } ICoreWebView2SourceChangedEventHandlerVtbl;
+
+ interface ICoreWebView2SourceChangedEventHandler
+ {
+ CONST_VTBL struct ICoreWebView2SourceChangedEventHandlerVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define ICoreWebView2SourceChangedEventHandler_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define ICoreWebView2SourceChangedEventHandler_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define ICoreWebView2SourceChangedEventHandler_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define ICoreWebView2SourceChangedEventHandler_Invoke(This,sender,args) \
+ ( (This)->lpVtbl -> Invoke(This,sender,args) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __ICoreWebView2SourceChangedEventHandler_INTERFACE_DEFINED__ */
+
+
+#ifndef __ICoreWebView2TrySuspendCompletedHandler_INTERFACE_DEFINED__
+#define __ICoreWebView2TrySuspendCompletedHandler_INTERFACE_DEFINED__
+
+/* interface ICoreWebView2TrySuspendCompletedHandler */
+/* [unique][object][uuid] */
+
+
+EXTERN_C __declspec(selectany) const IID IID_ICoreWebView2TrySuspendCompletedHandler = {0x00F206A7,0x9D17,0x4605,{0x91,0xF6,0x4E,0x8E,0x4D,0xE1,0x92,0xE3}};
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("00F206A7-9D17-4605-91F6-4E8E4DE192E3")
+ ICoreWebView2TrySuspendCompletedHandler : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE Invoke(
+ /* [in] */ HRESULT errorCode,
+ /* [in] */ BOOL isSuccessful) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct ICoreWebView2TrySuspendCompletedHandlerVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ ICoreWebView2TrySuspendCompletedHandler * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ ICoreWebView2TrySuspendCompletedHandler * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ ICoreWebView2TrySuspendCompletedHandler * This);
+
+ HRESULT ( STDMETHODCALLTYPE *Invoke )(
+ ICoreWebView2TrySuspendCompletedHandler * This,
+ /* [in] */ HRESULT errorCode,
+ /* [in] */ BOOL isSuccessful);
+
+ END_INTERFACE
+ } ICoreWebView2TrySuspendCompletedHandlerVtbl;
+
+ interface ICoreWebView2TrySuspendCompletedHandler
+ {
+ CONST_VTBL struct ICoreWebView2TrySuspendCompletedHandlerVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define ICoreWebView2TrySuspendCompletedHandler_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define ICoreWebView2TrySuspendCompletedHandler_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define ICoreWebView2TrySuspendCompletedHandler_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define ICoreWebView2TrySuspendCompletedHandler_Invoke(This,errorCode,isSuccessful) \
+ ( (This)->lpVtbl -> Invoke(This,errorCode,isSuccessful) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __ICoreWebView2TrySuspendCompletedHandler_INTERFACE_DEFINED__ */
+
+
+#ifndef __ICoreWebView2WebMessageReceivedEventArgs_INTERFACE_DEFINED__
+#define __ICoreWebView2WebMessageReceivedEventArgs_INTERFACE_DEFINED__
+
+/* interface ICoreWebView2WebMessageReceivedEventArgs */
+/* [unique][object][uuid] */
+
+
+EXTERN_C __declspec(selectany) const IID IID_ICoreWebView2WebMessageReceivedEventArgs = {0x0f99a40c,0xe962,0x4207,{0x9e,0x92,0xe3,0xd5,0x42,0xef,0xf8,0x49}};
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("0f99a40c-e962-4207-9e92-e3d542eff849")
+ ICoreWebView2WebMessageReceivedEventArgs : public IUnknown
+ {
+ public:
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_Source(
+ /* [retval][out] */ LPWSTR *source) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_WebMessageAsJson(
+ /* [retval][out] */ LPWSTR *webMessageAsJson) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE TryGetWebMessageAsString(
+ /* [retval][out] */ LPWSTR *webMessageAsString) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct ICoreWebView2WebMessageReceivedEventArgsVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ ICoreWebView2WebMessageReceivedEventArgs * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ ICoreWebView2WebMessageReceivedEventArgs * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ ICoreWebView2WebMessageReceivedEventArgs * This);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_Source )(
+ ICoreWebView2WebMessageReceivedEventArgs * This,
+ /* [retval][out] */ LPWSTR *source);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_WebMessageAsJson )(
+ ICoreWebView2WebMessageReceivedEventArgs * This,
+ /* [retval][out] */ LPWSTR *webMessageAsJson);
+
+ HRESULT ( STDMETHODCALLTYPE *TryGetWebMessageAsString )(
+ ICoreWebView2WebMessageReceivedEventArgs * This,
+ /* [retval][out] */ LPWSTR *webMessageAsString);
+
+ END_INTERFACE
+ } ICoreWebView2WebMessageReceivedEventArgsVtbl;
+
+ interface ICoreWebView2WebMessageReceivedEventArgs
+ {
+ CONST_VTBL struct ICoreWebView2WebMessageReceivedEventArgsVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define ICoreWebView2WebMessageReceivedEventArgs_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define ICoreWebView2WebMessageReceivedEventArgs_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define ICoreWebView2WebMessageReceivedEventArgs_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define ICoreWebView2WebMessageReceivedEventArgs_get_Source(This,source) \
+ ( (This)->lpVtbl -> get_Source(This,source) )
+
+#define ICoreWebView2WebMessageReceivedEventArgs_get_WebMessageAsJson(This,webMessageAsJson) \
+ ( (This)->lpVtbl -> get_WebMessageAsJson(This,webMessageAsJson) )
+
+#define ICoreWebView2WebMessageReceivedEventArgs_TryGetWebMessageAsString(This,webMessageAsString) \
+ ( (This)->lpVtbl -> TryGetWebMessageAsString(This,webMessageAsString) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __ICoreWebView2WebMessageReceivedEventArgs_INTERFACE_DEFINED__ */
+
+
+#ifndef __ICoreWebView2WebMessageReceivedEventHandler_INTERFACE_DEFINED__
+#define __ICoreWebView2WebMessageReceivedEventHandler_INTERFACE_DEFINED__
+
+/* interface ICoreWebView2WebMessageReceivedEventHandler */
+/* [unique][object][uuid] */
+
+
+EXTERN_C __declspec(selectany) const IID IID_ICoreWebView2WebMessageReceivedEventHandler = {0x57213f19,0x00e6,0x49fa,{0x8e,0x07,0x89,0x8e,0xa0,0x1e,0xcb,0xd2}};
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("57213f19-00e6-49fa-8e07-898ea01ecbd2")
+ ICoreWebView2WebMessageReceivedEventHandler : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE Invoke(
+ /* [in] */ ICoreWebView2 *sender,
+ /* [in] */ ICoreWebView2WebMessageReceivedEventArgs *args) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct ICoreWebView2WebMessageReceivedEventHandlerVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ ICoreWebView2WebMessageReceivedEventHandler * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ ICoreWebView2WebMessageReceivedEventHandler * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ ICoreWebView2WebMessageReceivedEventHandler * This);
+
+ HRESULT ( STDMETHODCALLTYPE *Invoke )(
+ ICoreWebView2WebMessageReceivedEventHandler * This,
+ /* [in] */ ICoreWebView2 *sender,
+ /* [in] */ ICoreWebView2WebMessageReceivedEventArgs *args);
+
+ END_INTERFACE
+ } ICoreWebView2WebMessageReceivedEventHandlerVtbl;
+
+ interface ICoreWebView2WebMessageReceivedEventHandler
+ {
+ CONST_VTBL struct ICoreWebView2WebMessageReceivedEventHandlerVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define ICoreWebView2WebMessageReceivedEventHandler_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define ICoreWebView2WebMessageReceivedEventHandler_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define ICoreWebView2WebMessageReceivedEventHandler_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define ICoreWebView2WebMessageReceivedEventHandler_Invoke(This,sender,args) \
+ ( (This)->lpVtbl -> Invoke(This,sender,args) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __ICoreWebView2WebMessageReceivedEventHandler_INTERFACE_DEFINED__ */
+
+
+#ifndef __ICoreWebView2WebResourceRequest_INTERFACE_DEFINED__
+#define __ICoreWebView2WebResourceRequest_INTERFACE_DEFINED__
+
+/* interface ICoreWebView2WebResourceRequest */
+/* [unique][object][uuid] */
+
+
+EXTERN_C __declspec(selectany) const IID IID_ICoreWebView2WebResourceRequest = {0x97055cd4,0x512c,0x4264,{0x8b,0x5f,0xe3,0xf4,0x46,0xce,0xa6,0xa5}};
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("97055cd4-512c-4264-8b5f-e3f446cea6a5")
+ ICoreWebView2WebResourceRequest : public IUnknown
+ {
+ public:
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_Uri(
+ /* [retval][out] */ LPWSTR *uri) = 0;
+
+ virtual /* [propput] */ HRESULT STDMETHODCALLTYPE put_Uri(
+ /* [in] */ LPCWSTR uri) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_Method(
+ /* [retval][out] */ LPWSTR *method) = 0;
+
+ virtual /* [propput] */ HRESULT STDMETHODCALLTYPE put_Method(
+ /* [in] */ LPCWSTR method) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_Content(
+ /* [retval][out] */ IStream **content) = 0;
+
+ virtual /* [propput] */ HRESULT STDMETHODCALLTYPE put_Content(
+ /* [in] */ IStream *content) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_Headers(
+ /* [retval][out] */ ICoreWebView2HttpRequestHeaders **headers) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct ICoreWebView2WebResourceRequestVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ ICoreWebView2WebResourceRequest * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ ICoreWebView2WebResourceRequest * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ ICoreWebView2WebResourceRequest * This);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_Uri )(
+ ICoreWebView2WebResourceRequest * This,
+ /* [retval][out] */ LPWSTR *uri);
+
+ /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_Uri )(
+ ICoreWebView2WebResourceRequest * This,
+ /* [in] */ LPCWSTR uri);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_Method )(
+ ICoreWebView2WebResourceRequest * This,
+ /* [retval][out] */ LPWSTR *method);
+
+ /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_Method )(
+ ICoreWebView2WebResourceRequest * This,
+ /* [in] */ LPCWSTR method);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_Content )(
+ ICoreWebView2WebResourceRequest * This,
+ /* [retval][out] */ IStream **content);
+
+ /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_Content )(
+ ICoreWebView2WebResourceRequest * This,
+ /* [in] */ IStream *content);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_Headers )(
+ ICoreWebView2WebResourceRequest * This,
+ /* [retval][out] */ ICoreWebView2HttpRequestHeaders **headers);
+
+ END_INTERFACE
+ } ICoreWebView2WebResourceRequestVtbl;
+
+ interface ICoreWebView2WebResourceRequest
+ {
+ CONST_VTBL struct ICoreWebView2WebResourceRequestVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define ICoreWebView2WebResourceRequest_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define ICoreWebView2WebResourceRequest_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define ICoreWebView2WebResourceRequest_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define ICoreWebView2WebResourceRequest_get_Uri(This,uri) \
+ ( (This)->lpVtbl -> get_Uri(This,uri) )
+
+#define ICoreWebView2WebResourceRequest_put_Uri(This,uri) \
+ ( (This)->lpVtbl -> put_Uri(This,uri) )
+
+#define ICoreWebView2WebResourceRequest_get_Method(This,method) \
+ ( (This)->lpVtbl -> get_Method(This,method) )
+
+#define ICoreWebView2WebResourceRequest_put_Method(This,method) \
+ ( (This)->lpVtbl -> put_Method(This,method) )
+
+#define ICoreWebView2WebResourceRequest_get_Content(This,content) \
+ ( (This)->lpVtbl -> get_Content(This,content) )
+
+#define ICoreWebView2WebResourceRequest_put_Content(This,content) \
+ ( (This)->lpVtbl -> put_Content(This,content) )
+
+#define ICoreWebView2WebResourceRequest_get_Headers(This,headers) \
+ ( (This)->lpVtbl -> get_Headers(This,headers) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __ICoreWebView2WebResourceRequest_INTERFACE_DEFINED__ */
+
+
+#ifndef __ICoreWebView2WebResourceRequestedEventArgs_INTERFACE_DEFINED__
+#define __ICoreWebView2WebResourceRequestedEventArgs_INTERFACE_DEFINED__
+
+/* interface ICoreWebView2WebResourceRequestedEventArgs */
+/* [unique][object][uuid] */
+
+
+EXTERN_C __declspec(selectany) const IID IID_ICoreWebView2WebResourceRequestedEventArgs = {0x453e667f,0x12c7,0x49d4,{0xbe,0x6d,0xdd,0xbe,0x79,0x56,0xf5,0x7a}};
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("453e667f-12c7-49d4-be6d-ddbe7956f57a")
+ ICoreWebView2WebResourceRequestedEventArgs : public IUnknown
+ {
+ public:
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_Request(
+ /* [retval][out] */ ICoreWebView2WebResourceRequest **request) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_Response(
+ /* [retval][out] */ ICoreWebView2WebResourceResponse **response) = 0;
+
+ virtual /* [propput] */ HRESULT STDMETHODCALLTYPE put_Response(
+ /* [in] */ ICoreWebView2WebResourceResponse *response) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetDeferral(
+ /* [retval][out] */ ICoreWebView2Deferral **deferral) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_ResourceContext(
+ /* [retval][out] */ COREWEBVIEW2_WEB_RESOURCE_CONTEXT *context) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct ICoreWebView2WebResourceRequestedEventArgsVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ ICoreWebView2WebResourceRequestedEventArgs * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ ICoreWebView2WebResourceRequestedEventArgs * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ ICoreWebView2WebResourceRequestedEventArgs * This);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_Request )(
+ ICoreWebView2WebResourceRequestedEventArgs * This,
+ /* [retval][out] */ ICoreWebView2WebResourceRequest **request);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_Response )(
+ ICoreWebView2WebResourceRequestedEventArgs * This,
+ /* [retval][out] */ ICoreWebView2WebResourceResponse **response);
+
+ /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_Response )(
+ ICoreWebView2WebResourceRequestedEventArgs * This,
+ /* [in] */ ICoreWebView2WebResourceResponse *response);
+
+ HRESULT ( STDMETHODCALLTYPE *GetDeferral )(
+ ICoreWebView2WebResourceRequestedEventArgs * This,
+ /* [retval][out] */ ICoreWebView2Deferral **deferral);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_ResourceContext )(
+ ICoreWebView2WebResourceRequestedEventArgs * This,
+ /* [retval][out] */ COREWEBVIEW2_WEB_RESOURCE_CONTEXT *context);
+
+ END_INTERFACE
+ } ICoreWebView2WebResourceRequestedEventArgsVtbl;
+
+ interface ICoreWebView2WebResourceRequestedEventArgs
+ {
+ CONST_VTBL struct ICoreWebView2WebResourceRequestedEventArgsVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define ICoreWebView2WebResourceRequestedEventArgs_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define ICoreWebView2WebResourceRequestedEventArgs_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define ICoreWebView2WebResourceRequestedEventArgs_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define ICoreWebView2WebResourceRequestedEventArgs_get_Request(This,request) \
+ ( (This)->lpVtbl -> get_Request(This,request) )
+
+#define ICoreWebView2WebResourceRequestedEventArgs_get_Response(This,response) \
+ ( (This)->lpVtbl -> get_Response(This,response) )
+
+#define ICoreWebView2WebResourceRequestedEventArgs_put_Response(This,response) \
+ ( (This)->lpVtbl -> put_Response(This,response) )
+
+#define ICoreWebView2WebResourceRequestedEventArgs_GetDeferral(This,deferral) \
+ ( (This)->lpVtbl -> GetDeferral(This,deferral) )
+
+#define ICoreWebView2WebResourceRequestedEventArgs_get_ResourceContext(This,context) \
+ ( (This)->lpVtbl -> get_ResourceContext(This,context) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __ICoreWebView2WebResourceRequestedEventArgs_INTERFACE_DEFINED__ */
+
+
+#ifndef __ICoreWebView2WebResourceRequestedEventHandler_INTERFACE_DEFINED__
+#define __ICoreWebView2WebResourceRequestedEventHandler_INTERFACE_DEFINED__
+
+/* interface ICoreWebView2WebResourceRequestedEventHandler */
+/* [unique][object][uuid] */
+
+
+EXTERN_C __declspec(selectany) const IID IID_ICoreWebView2WebResourceRequestedEventHandler = {0xab00b74c,0x15f1,0x4646,{0x80,0xe8,0xe7,0x63,0x41,0xd2,0x5d,0x71}};
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("ab00b74c-15f1-4646-80e8-e76341d25d71")
+ ICoreWebView2WebResourceRequestedEventHandler : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE Invoke(
+ /* [in] */ ICoreWebView2 *sender,
+ /* [in] */ ICoreWebView2WebResourceRequestedEventArgs *args) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct ICoreWebView2WebResourceRequestedEventHandlerVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ ICoreWebView2WebResourceRequestedEventHandler * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ ICoreWebView2WebResourceRequestedEventHandler * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ ICoreWebView2WebResourceRequestedEventHandler * This);
+
+ HRESULT ( STDMETHODCALLTYPE *Invoke )(
+ ICoreWebView2WebResourceRequestedEventHandler * This,
+ /* [in] */ ICoreWebView2 *sender,
+ /* [in] */ ICoreWebView2WebResourceRequestedEventArgs *args);
+
+ END_INTERFACE
+ } ICoreWebView2WebResourceRequestedEventHandlerVtbl;
+
+ interface ICoreWebView2WebResourceRequestedEventHandler
+ {
+ CONST_VTBL struct ICoreWebView2WebResourceRequestedEventHandlerVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define ICoreWebView2WebResourceRequestedEventHandler_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define ICoreWebView2WebResourceRequestedEventHandler_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define ICoreWebView2WebResourceRequestedEventHandler_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define ICoreWebView2WebResourceRequestedEventHandler_Invoke(This,sender,args) \
+ ( (This)->lpVtbl -> Invoke(This,sender,args) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __ICoreWebView2WebResourceRequestedEventHandler_INTERFACE_DEFINED__ */
+
+
+#ifndef __ICoreWebView2WebResourceResponse_INTERFACE_DEFINED__
+#define __ICoreWebView2WebResourceResponse_INTERFACE_DEFINED__
+
+/* interface ICoreWebView2WebResourceResponse */
+/* [unique][object][uuid] */
+
+
+EXTERN_C __declspec(selectany) const IID IID_ICoreWebView2WebResourceResponse = {0xaafcc94f,0xfa27,0x48fd,{0x97,0xdf,0x83,0x0e,0xf7,0x5a,0xae,0xc9}};
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("aafcc94f-fa27-48fd-97df-830ef75aaec9")
+ ICoreWebView2WebResourceResponse : public IUnknown
+ {
+ public:
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_Content(
+ /* [retval][out] */ IStream **content) = 0;
+
+ virtual /* [propput] */ HRESULT STDMETHODCALLTYPE put_Content(
+ /* [in] */ IStream *content) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_Headers(
+ /* [retval][out] */ ICoreWebView2HttpResponseHeaders **headers) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_StatusCode(
+ /* [retval][out] */ int *statusCode) = 0;
+
+ virtual /* [propput] */ HRESULT STDMETHODCALLTYPE put_StatusCode(
+ /* [in] */ int statusCode) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_ReasonPhrase(
+ /* [retval][out] */ LPWSTR *reasonPhrase) = 0;
+
+ virtual /* [propput] */ HRESULT STDMETHODCALLTYPE put_ReasonPhrase(
+ /* [in] */ LPCWSTR reasonPhrase) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct ICoreWebView2WebResourceResponseVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ ICoreWebView2WebResourceResponse * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ ICoreWebView2WebResourceResponse * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ ICoreWebView2WebResourceResponse * This);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_Content )(
+ ICoreWebView2WebResourceResponse * This,
+ /* [retval][out] */ IStream **content);
+
+ /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_Content )(
+ ICoreWebView2WebResourceResponse * This,
+ /* [in] */ IStream *content);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_Headers )(
+ ICoreWebView2WebResourceResponse * This,
+ /* [retval][out] */ ICoreWebView2HttpResponseHeaders **headers);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_StatusCode )(
+ ICoreWebView2WebResourceResponse * This,
+ /* [retval][out] */ int *statusCode);
+
+ /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_StatusCode )(
+ ICoreWebView2WebResourceResponse * This,
+ /* [in] */ int statusCode);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_ReasonPhrase )(
+ ICoreWebView2WebResourceResponse * This,
+ /* [retval][out] */ LPWSTR *reasonPhrase);
+
+ /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_ReasonPhrase )(
+ ICoreWebView2WebResourceResponse * This,
+ /* [in] */ LPCWSTR reasonPhrase);
+
+ END_INTERFACE
+ } ICoreWebView2WebResourceResponseVtbl;
+
+ interface ICoreWebView2WebResourceResponse
+ {
+ CONST_VTBL struct ICoreWebView2WebResourceResponseVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define ICoreWebView2WebResourceResponse_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define ICoreWebView2WebResourceResponse_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define ICoreWebView2WebResourceResponse_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define ICoreWebView2WebResourceResponse_get_Content(This,content) \
+ ( (This)->lpVtbl -> get_Content(This,content) )
+
+#define ICoreWebView2WebResourceResponse_put_Content(This,content) \
+ ( (This)->lpVtbl -> put_Content(This,content) )
+
+#define ICoreWebView2WebResourceResponse_get_Headers(This,headers) \
+ ( (This)->lpVtbl -> get_Headers(This,headers) )
+
+#define ICoreWebView2WebResourceResponse_get_StatusCode(This,statusCode) \
+ ( (This)->lpVtbl -> get_StatusCode(This,statusCode) )
+
+#define ICoreWebView2WebResourceResponse_put_StatusCode(This,statusCode) \
+ ( (This)->lpVtbl -> put_StatusCode(This,statusCode) )
+
+#define ICoreWebView2WebResourceResponse_get_ReasonPhrase(This,reasonPhrase) \
+ ( (This)->lpVtbl -> get_ReasonPhrase(This,reasonPhrase) )
+
+#define ICoreWebView2WebResourceResponse_put_ReasonPhrase(This,reasonPhrase) \
+ ( (This)->lpVtbl -> put_ReasonPhrase(This,reasonPhrase) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __ICoreWebView2WebResourceResponse_INTERFACE_DEFINED__ */
+
+
+#ifndef __ICoreWebView2WebResourceResponseReceivedEventHandler_INTERFACE_DEFINED__
+#define __ICoreWebView2WebResourceResponseReceivedEventHandler_INTERFACE_DEFINED__
+
+/* interface ICoreWebView2WebResourceResponseReceivedEventHandler */
+/* [unique][object][uuid] */
+
+
+EXTERN_C __declspec(selectany) const IID IID_ICoreWebView2WebResourceResponseReceivedEventHandler = {0x7DE9898A,0x24F5,0x40C3,{0xA2,0xDE,0xD4,0xF4,0x58,0xE6,0x98,0x28}};
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("7DE9898A-24F5-40C3-A2DE-D4F458E69828")
+ ICoreWebView2WebResourceResponseReceivedEventHandler : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE Invoke(
+ /* [in] */ ICoreWebView2 *sender,
+ /* [in] */ ICoreWebView2WebResourceResponseReceivedEventArgs *args) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct ICoreWebView2WebResourceResponseReceivedEventHandlerVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ ICoreWebView2WebResourceResponseReceivedEventHandler * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ ICoreWebView2WebResourceResponseReceivedEventHandler * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ ICoreWebView2WebResourceResponseReceivedEventHandler * This);
+
+ HRESULT ( STDMETHODCALLTYPE *Invoke )(
+ ICoreWebView2WebResourceResponseReceivedEventHandler * This,
+ /* [in] */ ICoreWebView2 *sender,
+ /* [in] */ ICoreWebView2WebResourceResponseReceivedEventArgs *args);
+
+ END_INTERFACE
+ } ICoreWebView2WebResourceResponseReceivedEventHandlerVtbl;
+
+ interface ICoreWebView2WebResourceResponseReceivedEventHandler
+ {
+ CONST_VTBL struct ICoreWebView2WebResourceResponseReceivedEventHandlerVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define ICoreWebView2WebResourceResponseReceivedEventHandler_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define ICoreWebView2WebResourceResponseReceivedEventHandler_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define ICoreWebView2WebResourceResponseReceivedEventHandler_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define ICoreWebView2WebResourceResponseReceivedEventHandler_Invoke(This,sender,args) \
+ ( (This)->lpVtbl -> Invoke(This,sender,args) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __ICoreWebView2WebResourceResponseReceivedEventHandler_INTERFACE_DEFINED__ */
+
+
+#ifndef __ICoreWebView2WebResourceResponseReceivedEventArgs_INTERFACE_DEFINED__
+#define __ICoreWebView2WebResourceResponseReceivedEventArgs_INTERFACE_DEFINED__
+
+/* interface ICoreWebView2WebResourceResponseReceivedEventArgs */
+/* [unique][object][uuid] */
+
+
+EXTERN_C __declspec(selectany) const IID IID_ICoreWebView2WebResourceResponseReceivedEventArgs = {0xD1DB483D,0x6796,0x4B8B,{0x80,0xFC,0x13,0x71,0x2B,0xB7,0x16,0xF4}};
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("D1DB483D-6796-4B8B-80FC-13712BB716F4")
+ ICoreWebView2WebResourceResponseReceivedEventArgs : public IUnknown
+ {
+ public:
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_Request(
+ /* [retval][out] */ ICoreWebView2WebResourceRequest **request) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_Response(
+ /* [retval][out] */ ICoreWebView2WebResourceResponseView **response) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct ICoreWebView2WebResourceResponseReceivedEventArgsVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ ICoreWebView2WebResourceResponseReceivedEventArgs * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ ICoreWebView2WebResourceResponseReceivedEventArgs * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ ICoreWebView2WebResourceResponseReceivedEventArgs * This);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_Request )(
+ ICoreWebView2WebResourceResponseReceivedEventArgs * This,
+ /* [retval][out] */ ICoreWebView2WebResourceRequest **request);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_Response )(
+ ICoreWebView2WebResourceResponseReceivedEventArgs * This,
+ /* [retval][out] */ ICoreWebView2WebResourceResponseView **response);
+
+ END_INTERFACE
+ } ICoreWebView2WebResourceResponseReceivedEventArgsVtbl;
+
+ interface ICoreWebView2WebResourceResponseReceivedEventArgs
+ {
+ CONST_VTBL struct ICoreWebView2WebResourceResponseReceivedEventArgsVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define ICoreWebView2WebResourceResponseReceivedEventArgs_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define ICoreWebView2WebResourceResponseReceivedEventArgs_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define ICoreWebView2WebResourceResponseReceivedEventArgs_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define ICoreWebView2WebResourceResponseReceivedEventArgs_get_Request(This,request) \
+ ( (This)->lpVtbl -> get_Request(This,request) )
+
+#define ICoreWebView2WebResourceResponseReceivedEventArgs_get_Response(This,response) \
+ ( (This)->lpVtbl -> get_Response(This,response) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __ICoreWebView2WebResourceResponseReceivedEventArgs_INTERFACE_DEFINED__ */
+
+
+#ifndef __ICoreWebView2WebResourceResponseView_INTERFACE_DEFINED__
+#define __ICoreWebView2WebResourceResponseView_INTERFACE_DEFINED__
+
+/* interface ICoreWebView2WebResourceResponseView */
+/* [unique][object][uuid] */
+
+
+EXTERN_C __declspec(selectany) const IID IID_ICoreWebView2WebResourceResponseView = {0x79701053,0x7759,0x4162,{0x8F,0x7D,0xF1,0xB3,0xF0,0x84,0x92,0x8D}};
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("79701053-7759-4162-8F7D-F1B3F084928D")
+ ICoreWebView2WebResourceResponseView : public IUnknown
+ {
+ public:
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_Headers(
+ /* [retval][out] */ ICoreWebView2HttpResponseHeaders **headers) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_StatusCode(
+ /* [retval][out] */ int *statusCode) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_ReasonPhrase(
+ /* [retval][out] */ LPWSTR *reasonPhrase) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetContent(
+ /* [in] */ ICoreWebView2WebResourceResponseViewGetContentCompletedHandler *handler) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct ICoreWebView2WebResourceResponseViewVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ ICoreWebView2WebResourceResponseView * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ ICoreWebView2WebResourceResponseView * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ ICoreWebView2WebResourceResponseView * This);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_Headers )(
+ ICoreWebView2WebResourceResponseView * This,
+ /* [retval][out] */ ICoreWebView2HttpResponseHeaders **headers);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_StatusCode )(
+ ICoreWebView2WebResourceResponseView * This,
+ /* [retval][out] */ int *statusCode);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_ReasonPhrase )(
+ ICoreWebView2WebResourceResponseView * This,
+ /* [retval][out] */ LPWSTR *reasonPhrase);
+
+ HRESULT ( STDMETHODCALLTYPE *GetContent )(
+ ICoreWebView2WebResourceResponseView * This,
+ /* [in] */ ICoreWebView2WebResourceResponseViewGetContentCompletedHandler *handler);
+
+ END_INTERFACE
+ } ICoreWebView2WebResourceResponseViewVtbl;
+
+ interface ICoreWebView2WebResourceResponseView
+ {
+ CONST_VTBL struct ICoreWebView2WebResourceResponseViewVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define ICoreWebView2WebResourceResponseView_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define ICoreWebView2WebResourceResponseView_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define ICoreWebView2WebResourceResponseView_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define ICoreWebView2WebResourceResponseView_get_Headers(This,headers) \
+ ( (This)->lpVtbl -> get_Headers(This,headers) )
+
+#define ICoreWebView2WebResourceResponseView_get_StatusCode(This,statusCode) \
+ ( (This)->lpVtbl -> get_StatusCode(This,statusCode) )
+
+#define ICoreWebView2WebResourceResponseView_get_ReasonPhrase(This,reasonPhrase) \
+ ( (This)->lpVtbl -> get_ReasonPhrase(This,reasonPhrase) )
+
+#define ICoreWebView2WebResourceResponseView_GetContent(This,handler) \
+ ( (This)->lpVtbl -> GetContent(This,handler) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __ICoreWebView2WebResourceResponseView_INTERFACE_DEFINED__ */
+
+
+#ifndef __ICoreWebView2WebResourceResponseViewGetContentCompletedHandler_INTERFACE_DEFINED__
+#define __ICoreWebView2WebResourceResponseViewGetContentCompletedHandler_INTERFACE_DEFINED__
+
+/* interface ICoreWebView2WebResourceResponseViewGetContentCompletedHandler */
+/* [unique][object][uuid] */
+
+
+EXTERN_C __declspec(selectany) const IID IID_ICoreWebView2WebResourceResponseViewGetContentCompletedHandler = {0x875738E1,0x9FA2,0x40E3,{0x8B,0x74,0x2E,0x89,0x72,0xDD,0x6F,0xE7}};
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("875738E1-9FA2-40E3-8B74-2E8972DD6FE7")
+ ICoreWebView2WebResourceResponseViewGetContentCompletedHandler : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE Invoke(
+ /* [in] */ HRESULT errorCode,
+ /* [in] */ IStream *content) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct ICoreWebView2WebResourceResponseViewGetContentCompletedHandlerVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ ICoreWebView2WebResourceResponseViewGetContentCompletedHandler * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ ICoreWebView2WebResourceResponseViewGetContentCompletedHandler * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ ICoreWebView2WebResourceResponseViewGetContentCompletedHandler * This);
+
+ HRESULT ( STDMETHODCALLTYPE *Invoke )(
+ ICoreWebView2WebResourceResponseViewGetContentCompletedHandler * This,
+ /* [in] */ HRESULT errorCode,
+ /* [in] */ IStream *content);
+
+ END_INTERFACE
+ } ICoreWebView2WebResourceResponseViewGetContentCompletedHandlerVtbl;
+
+ interface ICoreWebView2WebResourceResponseViewGetContentCompletedHandler
+ {
+ CONST_VTBL struct ICoreWebView2WebResourceResponseViewGetContentCompletedHandlerVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define ICoreWebView2WebResourceResponseViewGetContentCompletedHandler_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define ICoreWebView2WebResourceResponseViewGetContentCompletedHandler_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define ICoreWebView2WebResourceResponseViewGetContentCompletedHandler_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define ICoreWebView2WebResourceResponseViewGetContentCompletedHandler_Invoke(This,errorCode,content) \
+ ( (This)->lpVtbl -> Invoke(This,errorCode,content) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __ICoreWebView2WebResourceResponseViewGetContentCompletedHandler_INTERFACE_DEFINED__ */
+
+
+#ifndef __ICoreWebView2WindowCloseRequestedEventHandler_INTERFACE_DEFINED__
+#define __ICoreWebView2WindowCloseRequestedEventHandler_INTERFACE_DEFINED__
+
+/* interface ICoreWebView2WindowCloseRequestedEventHandler */
+/* [unique][object][uuid] */
+
+
+EXTERN_C __declspec(selectany) const IID IID_ICoreWebView2WindowCloseRequestedEventHandler = {0x5c19e9e0,0x092f,0x486b,{0xaf,0xfa,0xca,0x82,0x31,0x91,0x30,0x39}};
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("5c19e9e0-092f-486b-affa-ca8231913039")
+ ICoreWebView2WindowCloseRequestedEventHandler : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE Invoke(
+ /* [in] */ ICoreWebView2 *sender,
+ /* [in] */ IUnknown *args) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct ICoreWebView2WindowCloseRequestedEventHandlerVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ ICoreWebView2WindowCloseRequestedEventHandler * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ ICoreWebView2WindowCloseRequestedEventHandler * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ ICoreWebView2WindowCloseRequestedEventHandler * This);
+
+ HRESULT ( STDMETHODCALLTYPE *Invoke )(
+ ICoreWebView2WindowCloseRequestedEventHandler * This,
+ /* [in] */ ICoreWebView2 *sender,
+ /* [in] */ IUnknown *args);
+
+ END_INTERFACE
+ } ICoreWebView2WindowCloseRequestedEventHandlerVtbl;
+
+ interface ICoreWebView2WindowCloseRequestedEventHandler
+ {
+ CONST_VTBL struct ICoreWebView2WindowCloseRequestedEventHandlerVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define ICoreWebView2WindowCloseRequestedEventHandler_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define ICoreWebView2WindowCloseRequestedEventHandler_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define ICoreWebView2WindowCloseRequestedEventHandler_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define ICoreWebView2WindowCloseRequestedEventHandler_Invoke(This,sender,args) \
+ ( (This)->lpVtbl -> Invoke(This,sender,args) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __ICoreWebView2WindowCloseRequestedEventHandler_INTERFACE_DEFINED__ */
+
+
+#ifndef __ICoreWebView2WindowFeatures_INTERFACE_DEFINED__
+#define __ICoreWebView2WindowFeatures_INTERFACE_DEFINED__
+
+/* interface ICoreWebView2WindowFeatures */
+/* [unique][object][uuid] */
+
+
+EXTERN_C __declspec(selectany) const IID IID_ICoreWebView2WindowFeatures = {0x5eaf559f,0xb46e,0x4397,{0x88,0x60,0xe4,0x22,0xf2,0x87,0xff,0x1e}};
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("5eaf559f-b46e-4397-8860-e422f287ff1e")
+ ICoreWebView2WindowFeatures : public IUnknown
+ {
+ public:
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_HasPosition(
+ /* [retval][out] */ BOOL *value) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_HasSize(
+ /* [retval][out] */ BOOL *value) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_Left(
+ /* [retval][out] */ UINT32 *value) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_Top(
+ /* [retval][out] */ UINT32 *value) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_Height(
+ /* [retval][out] */ UINT32 *value) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_Width(
+ /* [retval][out] */ UINT32 *value) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_ShouldDisplayMenuBar(
+ /* [retval][out] */ BOOL *value) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_ShouldDisplayStatus(
+ /* [retval][out] */ BOOL *value) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_ShouldDisplayToolbar(
+ /* [retval][out] */ BOOL *value) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_ShouldDisplayScrollBars(
+ /* [retval][out] */ BOOL *value) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct ICoreWebView2WindowFeaturesVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ ICoreWebView2WindowFeatures * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ ICoreWebView2WindowFeatures * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ ICoreWebView2WindowFeatures * This);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_HasPosition )(
+ ICoreWebView2WindowFeatures * This,
+ /* [retval][out] */ BOOL *value);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_HasSize )(
+ ICoreWebView2WindowFeatures * This,
+ /* [retval][out] */ BOOL *value);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_Left )(
+ ICoreWebView2WindowFeatures * This,
+ /* [retval][out] */ UINT32 *value);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_Top )(
+ ICoreWebView2WindowFeatures * This,
+ /* [retval][out] */ UINT32 *value);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_Height )(
+ ICoreWebView2WindowFeatures * This,
+ /* [retval][out] */ UINT32 *value);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_Width )(
+ ICoreWebView2WindowFeatures * This,
+ /* [retval][out] */ UINT32 *value);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_ShouldDisplayMenuBar )(
+ ICoreWebView2WindowFeatures * This,
+ /* [retval][out] */ BOOL *value);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_ShouldDisplayStatus )(
+ ICoreWebView2WindowFeatures * This,
+ /* [retval][out] */ BOOL *value);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_ShouldDisplayToolbar )(
+ ICoreWebView2WindowFeatures * This,
+ /* [retval][out] */ BOOL *value);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_ShouldDisplayScrollBars )(
+ ICoreWebView2WindowFeatures * This,
+ /* [retval][out] */ BOOL *value);
+
+ END_INTERFACE
+ } ICoreWebView2WindowFeaturesVtbl;
+
+ interface ICoreWebView2WindowFeatures
+ {
+ CONST_VTBL struct ICoreWebView2WindowFeaturesVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define ICoreWebView2WindowFeatures_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define ICoreWebView2WindowFeatures_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define ICoreWebView2WindowFeatures_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define ICoreWebView2WindowFeatures_get_HasPosition(This,value) \
+ ( (This)->lpVtbl -> get_HasPosition(This,value) )
+
+#define ICoreWebView2WindowFeatures_get_HasSize(This,value) \
+ ( (This)->lpVtbl -> get_HasSize(This,value) )
+
+#define ICoreWebView2WindowFeatures_get_Left(This,value) \
+ ( (This)->lpVtbl -> get_Left(This,value) )
+
+#define ICoreWebView2WindowFeatures_get_Top(This,value) \
+ ( (This)->lpVtbl -> get_Top(This,value) )
+
+#define ICoreWebView2WindowFeatures_get_Height(This,value) \
+ ( (This)->lpVtbl -> get_Height(This,value) )
+
+#define ICoreWebView2WindowFeatures_get_Width(This,value) \
+ ( (This)->lpVtbl -> get_Width(This,value) )
+
+#define ICoreWebView2WindowFeatures_get_ShouldDisplayMenuBar(This,value) \
+ ( (This)->lpVtbl -> get_ShouldDisplayMenuBar(This,value) )
+
+#define ICoreWebView2WindowFeatures_get_ShouldDisplayStatus(This,value) \
+ ( (This)->lpVtbl -> get_ShouldDisplayStatus(This,value) )
+
+#define ICoreWebView2WindowFeatures_get_ShouldDisplayToolbar(This,value) \
+ ( (This)->lpVtbl -> get_ShouldDisplayToolbar(This,value) )
+
+#define ICoreWebView2WindowFeatures_get_ShouldDisplayScrollBars(This,value) \
+ ( (This)->lpVtbl -> get_ShouldDisplayScrollBars(This,value) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __ICoreWebView2WindowFeatures_INTERFACE_DEFINED__ */
+
+
+#ifndef __ICoreWebView2ZoomFactorChangedEventHandler_INTERFACE_DEFINED__
+#define __ICoreWebView2ZoomFactorChangedEventHandler_INTERFACE_DEFINED__
+
+/* interface ICoreWebView2ZoomFactorChangedEventHandler */
+/* [unique][object][uuid] */
+
+
+EXTERN_C __declspec(selectany) const IID IID_ICoreWebView2ZoomFactorChangedEventHandler = {0xb52d71d6,0xc4df,0x4543,{0xa9,0x0c,0x64,0xa3,0xe6,0x0f,0x38,0xcb}};
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("b52d71d6-c4df-4543-a90c-64a3e60f38cb")
+ ICoreWebView2ZoomFactorChangedEventHandler : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE Invoke(
+ /* [in] */ ICoreWebView2Controller *sender,
+ /* [in] */ IUnknown *args) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct ICoreWebView2ZoomFactorChangedEventHandlerVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ ICoreWebView2ZoomFactorChangedEventHandler * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ ICoreWebView2ZoomFactorChangedEventHandler * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ ICoreWebView2ZoomFactorChangedEventHandler * This);
+
+ HRESULT ( STDMETHODCALLTYPE *Invoke )(
+ ICoreWebView2ZoomFactorChangedEventHandler * This,
+ /* [in] */ ICoreWebView2Controller *sender,
+ /* [in] */ IUnknown *args);
+
+ END_INTERFACE
+ } ICoreWebView2ZoomFactorChangedEventHandlerVtbl;
+
+ interface ICoreWebView2ZoomFactorChangedEventHandler
+ {
+ CONST_VTBL struct ICoreWebView2ZoomFactorChangedEventHandlerVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define ICoreWebView2ZoomFactorChangedEventHandler_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define ICoreWebView2ZoomFactorChangedEventHandler_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define ICoreWebView2ZoomFactorChangedEventHandler_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define ICoreWebView2ZoomFactorChangedEventHandler_Invoke(This,sender,args) \
+ ( (This)->lpVtbl -> Invoke(This,sender,args) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __ICoreWebView2ZoomFactorChangedEventHandler_INTERFACE_DEFINED__ */
+
+
+#ifndef __ICoreWebView2CompositionControllerInterop_INTERFACE_DEFINED__
+#define __ICoreWebView2CompositionControllerInterop_INTERFACE_DEFINED__
+
+/* interface ICoreWebView2CompositionControllerInterop */
+/* [unique][object][uuid] */
+
+
+EXTERN_C __declspec(selectany) const IID IID_ICoreWebView2CompositionControllerInterop = {0x8e9922ce,0x9c80,0x42e6,{0xba,0xd7,0xfc,0xeb,0xf2,0x91,0xa4,0x95}};
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("8e9922ce-9c80-42e6-bad7-fcebf291a495")
+ ICoreWebView2CompositionControllerInterop : public IUnknown
+ {
+ public:
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_UIAProvider(
+ /* [retval][out] */ IUnknown **provider) = 0;
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_RootVisualTarget(
+ /* [retval][out] */ IUnknown **target) = 0;
+
+ virtual /* [propput] */ HRESULT STDMETHODCALLTYPE put_RootVisualTarget(
+ /* [in] */ IUnknown *target) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct ICoreWebView2CompositionControllerInteropVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ ICoreWebView2CompositionControllerInterop * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ ICoreWebView2CompositionControllerInterop * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ ICoreWebView2CompositionControllerInterop * This);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_UIAProvider )(
+ ICoreWebView2CompositionControllerInterop * This,
+ /* [retval][out] */ IUnknown **provider);
+
+ /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_RootVisualTarget )(
+ ICoreWebView2CompositionControllerInterop * This,
+ /* [retval][out] */ IUnknown **target);
+
+ /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_RootVisualTarget )(
+ ICoreWebView2CompositionControllerInterop * This,
+ /* [in] */ IUnknown *target);
+
+ END_INTERFACE
+ } ICoreWebView2CompositionControllerInteropVtbl;
+
+ interface ICoreWebView2CompositionControllerInterop
+ {
+ CONST_VTBL struct ICoreWebView2CompositionControllerInteropVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define ICoreWebView2CompositionControllerInterop_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define ICoreWebView2CompositionControllerInterop_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define ICoreWebView2CompositionControllerInterop_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define ICoreWebView2CompositionControllerInterop_get_UIAProvider(This,provider) \
+ ( (This)->lpVtbl -> get_UIAProvider(This,provider) )
+
+#define ICoreWebView2CompositionControllerInterop_get_RootVisualTarget(This,target) \
+ ( (This)->lpVtbl -> get_RootVisualTarget(This,target) )
+
+#define ICoreWebView2CompositionControllerInterop_put_RootVisualTarget(This,target) \
+ ( (This)->lpVtbl -> put_RootVisualTarget(This,target) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __ICoreWebView2CompositionControllerInterop_INTERFACE_DEFINED__ */
+
+
+#ifndef __ICoreWebView2EnvironmentInterop_INTERFACE_DEFINED__
+#define __ICoreWebView2EnvironmentInterop_INTERFACE_DEFINED__
+
+/* interface ICoreWebView2EnvironmentInterop */
+/* [unique][object][uuid] */
+
+
+EXTERN_C __declspec(selectany) const IID IID_ICoreWebView2EnvironmentInterop = {0xee503a63,0xc1e2,0x4fbf,{0x8a,0x4d,0x82,0x4e,0x95,0xf8,0xbb,0x13}};
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("ee503a63-c1e2-4fbf-8a4d-824e95f8bb13")
+ ICoreWebView2EnvironmentInterop : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE GetProviderForHwnd(
+ /* [in] */ HWND hwnd,
+ /* [retval][out] */ IUnknown **provider) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct ICoreWebView2EnvironmentInteropVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ ICoreWebView2EnvironmentInterop * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ ICoreWebView2EnvironmentInterop * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ ICoreWebView2EnvironmentInterop * This);
+
+ HRESULT ( STDMETHODCALLTYPE *GetProviderForHwnd )(
+ ICoreWebView2EnvironmentInterop * This,
+ /* [in] */ HWND hwnd,
+ /* [retval][out] */ IUnknown **provider);
+
+ END_INTERFACE
+ } ICoreWebView2EnvironmentInteropVtbl;
+
+ interface ICoreWebView2EnvironmentInterop
+ {
+ CONST_VTBL struct ICoreWebView2EnvironmentInteropVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define ICoreWebView2EnvironmentInterop_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define ICoreWebView2EnvironmentInterop_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define ICoreWebView2EnvironmentInterop_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define ICoreWebView2EnvironmentInterop_GetProviderForHwnd(This,hwnd,provider) \
+ ( (This)->lpVtbl -> GetProviderForHwnd(This,hwnd,provider) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __ICoreWebView2EnvironmentInterop_INTERFACE_DEFINED__ */
+
+#endif /* __WebView2_LIBRARY_DEFINED__ */
+
+/* Additional Prototypes for ALL interfaces */
+
+/* end of Additional Prototypes */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+
diff --git a/v2/internal/ffenestri/windows/WebView2EnvironmentOptions.h b/v2/internal/ffenestri/windows/WebView2EnvironmentOptions.h
new file mode 100644
index 000000000..6475ce58a
--- /dev/null
+++ b/v2/internal/ffenestri/windows/WebView2EnvironmentOptions.h
@@ -0,0 +1,144 @@
+// Copyright (C) Microsoft Corporation. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef __core_webview2_environment_options_h__
+#define __core_webview2_environment_options_h__
+
+#include
+#include
+
+#include "webview2.h"
+#define CORE_WEBVIEW_TARGET_PRODUCT_VERSION L"91.0.864.35"
+
+#define COREWEBVIEW2ENVIRONMENTOPTIONS_STRING_PROPERTY(p) \
+ public: \
+ HRESULT STDMETHODCALLTYPE get_##p(LPWSTR* value) override { \
+ if (!value) \
+ return E_POINTER; \
+ *value = m_##p.Copy(); \
+ if ((*value == nullptr) && (m_##p.Get() != nullptr)) \
+ return HRESULT_FROM_WIN32(GetLastError()); \
+ return S_OK; \
+ } \
+ HRESULT STDMETHODCALLTYPE put_##p(LPCWSTR value) override { \
+ LPCWSTR result = m_##p.Set(value); \
+ if ((result == nullptr) && (value != nullptr)) \
+ return HRESULT_FROM_WIN32(GetLastError()); \
+ return S_OK; \
+ } \
+ \
+ protected: \
+ AutoCoMemString m_##p;
+
+#define COREWEBVIEW2ENVIRONMENTOPTIONS_BOOL_PROPERTY(p) \
+ public: \
+ HRESULT STDMETHODCALLTYPE get_##p(BOOL* value) override { \
+ if (!value) \
+ return E_POINTER; \
+ *value = m_##p; \
+ return S_OK; \
+ } \
+ HRESULT STDMETHODCALLTYPE put_##p(BOOL value) override { \
+ m_##p = value; \
+ return S_OK; \
+ } \
+ \
+ protected: \
+ BOOL m_##p = FALSE;
+
+// This is a base COM class that implements ICoreWebView2EnvironmentOptions.
+template
+class CoreWebView2EnvironmentOptionsBase
+ : public Microsoft::WRL::Implements<
+ Microsoft::WRL::RuntimeClassFlags,
+ ICoreWebView2EnvironmentOptions> {
+ public:
+ CoreWebView2EnvironmentOptionsBase() {
+ // Initialize the target compatible browser version value to the version of
+ // the browser binaries corresponding to this version of the SDK.
+ m_TargetCompatibleBrowserVersion.Set(CORE_WEBVIEW_TARGET_PRODUCT_VERSION);
+ }
+
+ protected:
+ ~CoreWebView2EnvironmentOptionsBase(){};
+
+ class AutoCoMemString {
+ public:
+ AutoCoMemString() {}
+ ~AutoCoMemString() { Release(); }
+ void Release() {
+ if (m_string) {
+ deallocate_fn(m_string);
+ m_string = nullptr;
+ }
+ }
+
+ LPCWSTR Set(LPCWSTR str) {
+ Release();
+ if (str) {
+ m_string = MakeCoMemString(str);
+ }
+ return m_string;
+ }
+ LPCWSTR Get() { return m_string; }
+ LPWSTR Copy() {
+ if (m_string)
+ return MakeCoMemString(m_string);
+ return nullptr;
+ }
+
+ protected:
+ LPWSTR MakeCoMemString(LPCWSTR source) {
+ const size_t length = wcslen(source);
+ const size_t bytes = (length + 1) * sizeof(*source);
+ // Ensure we didn't overflow during our size calculation.
+ if (bytes <= length) {
+ return nullptr;
+ }
+
+ wchar_t* result = reinterpret_cast(allocate_fn(bytes));
+ if (result)
+ memcpy(result, source, bytes);
+
+ return result;
+ }
+
+ LPWSTR m_string = nullptr;
+ };
+
+ COREWEBVIEW2ENVIRONMENTOPTIONS_STRING_PROPERTY(AdditionalBrowserArguments)
+ COREWEBVIEW2ENVIRONMENTOPTIONS_STRING_PROPERTY(Language)
+ COREWEBVIEW2ENVIRONMENTOPTIONS_STRING_PROPERTY(TargetCompatibleBrowserVersion)
+ COREWEBVIEW2ENVIRONMENTOPTIONS_BOOL_PROPERTY(
+ AllowSingleSignOnUsingOSPrimaryAccount)
+};
+
+template
+class CoreWebView2EnvironmentOptionsBaseClass
+ : public Microsoft::WRL::RuntimeClass<
+ Microsoft::WRL::RuntimeClassFlags,
+ CoreWebView2EnvironmentOptionsBase> {
+ public:
+ CoreWebView2EnvironmentOptionsBaseClass() {}
+
+ protected:
+ ~CoreWebView2EnvironmentOptionsBaseClass() override{};
+};
+
+typedef CoreWebView2EnvironmentOptionsBaseClass
+ CoreWebView2EnvironmentOptions;
+
+#endif // __core_webview2_environment_options_h__
diff --git a/v2/internal/ffenestri/windows/scripts/README.md b/v2/internal/ffenestri/windows/scripts/README.md
new file mode 100644
index 000000000..634e3596b
--- /dev/null
+++ b/v2/internal/ffenestri/windows/scripts/README.md
@@ -0,0 +1,11 @@
+# Build
+
+This script will download the given webview2 sdk version and copy out the files necessary for building Wails apps.
+
+## Prerequistes
+
+ - nuget
+
+## Usage
+
+`updatesdk.bat `
diff --git a/v2/internal/ffenestri/windows/scripts/sdkversion.txt b/v2/internal/ffenestri/windows/scripts/sdkversion.txt
new file mode 100644
index 000000000..e4c251ea5
--- /dev/null
+++ b/v2/internal/ffenestri/windows/scripts/sdkversion.txt
@@ -0,0 +1 @@
+The version of WebView2 SDK used: 1.0.992.28
diff --git a/v2/internal/ffenestri/windows/scripts/updatesdk.bat b/v2/internal/ffenestri/windows/scripts/updatesdk.bat
new file mode 100644
index 000000000..780c09128
--- /dev/null
+++ b/v2/internal/ffenestri/windows/scripts/updatesdk.bat
@@ -0,0 +1,18 @@
+@echo off
+IF %1.==. GOTO NoVersion
+nuget install microsoft.web.webview2 -Version %1 -OutputDirectory . >NUL || goto :eof
+echo Downloaded microsoft.web.webview2.%1
+
+set sdk_version=%1
+set native_dir="%~dp0\microsoft.web.webview2.%sdk_version%\build\native"
+copy "%native_dir%\include\*.h" .. >NUL
+copy "%native_dir%\x64\WebView2Loader.dll" "..\x64" >NUL
+@REM @rd /S /Q "microsoft.web.webview2.%sdk_version%"
+del /s version.txt >nul 2>&1
+echo The version of WebView2 SDK used: %sdk_version% > sdkversion.txt
+echo SDK updated to %sdk_version%
+goto :eof
+
+:NoVersion
+ echo Please provide a version number, EG: 1.0.664.37
+ goto :eof
diff --git a/v2/internal/ffenestri/windows/wv2runtime/browser.go b/v2/internal/ffenestri/windows/wv2runtime/browser.go
new file mode 100644
index 000000000..25f19f2e0
--- /dev/null
+++ b/v2/internal/ffenestri/windows/wv2runtime/browser.go
@@ -0,0 +1,23 @@
+// +build wv2runtime.browser
+
+package wv2runtime
+
+import (
+ "fmt"
+ "github.com/leaanthony/webview2runtime"
+)
+
+func doInstallationStrategy(installStatus installationStatus) error {
+ confirmed, err := webview2runtime.Confirm("This application requires the WebView2 runtime. Press OK to open the download page. Minimum version required: "+MinimumRuntimeVersion, "Missing Requirements")
+ if err != nil {
+ return err
+ }
+ if confirmed {
+ err = webview2runtime.OpenInstallerDownloadWebpage()
+ if err != nil {
+ return err
+ }
+ }
+
+ return fmt.Errorf("webview2 runtime not installed")
+}
diff --git a/v2/internal/ffenestri/windows/wv2runtime/download.go b/v2/internal/ffenestri/windows/wv2runtime/download.go
new file mode 100644
index 000000000..cfb2aa197
--- /dev/null
+++ b/v2/internal/ffenestri/windows/wv2runtime/download.go
@@ -0,0 +1,35 @@
+// +build !wv2runtime.error
+// +build !wv2runtime.browser
+// +build !wv2runtime.embed
+
+package wv2runtime
+
+import (
+ "fmt"
+ "github.com/leaanthony/webview2runtime"
+)
+
+func doInstallationStrategy(installStatus installationStatus) error {
+ message := "The WebView2 runtime is required. "
+ if installStatus == needsUpdating {
+ message = "The Webview2 runtime needs updating. "
+ }
+ message += "Press Ok to download and install. Note: The installer will download silently so please wait."
+ confirmed, err := webview2runtime.Confirm(message, "Missing Requirements")
+ if err != nil {
+ return err
+ }
+ if !confirmed {
+ return fmt.Errorf("webview2 runtime not installed")
+ }
+ installedCorrectly, err := webview2runtime.InstallUsingBootstrapper()
+ if err != nil {
+ _ = webview2runtime.Error(err.Error(), "Error")
+ return err
+ }
+ if !installedCorrectly {
+ err = webview2runtime.Error("The runtime failed to install correctly. Please try again.", "Error")
+ return err
+ }
+ return nil
+}
diff --git a/v2/internal/ffenestri/windows/wv2runtime/embed.go b/v2/internal/ffenestri/windows/wv2runtime/embed.go
new file mode 100644
index 000000000..99a472d48
--- /dev/null
+++ b/v2/internal/ffenestri/windows/wv2runtime/embed.go
@@ -0,0 +1,33 @@
+// +build wv2runtime.embed
+
+package wv2runtime
+
+import (
+ "fmt"
+ "github.com/leaanthony/webview2runtime"
+)
+
+func doInstallationStrategy(installStatus installationStatus) error {
+ message := "The WebView2 runtime is required. "
+ if installStatus == needsUpdating {
+ message = "The Webview2 runtime needs updating. "
+ }
+ message += "Press Ok to install."
+ confirmed, err := webview2runtime.Confirm(message, "Missing Requirements")
+ if err != nil {
+ return err
+ }
+ if !confirmed {
+ return fmt.Errorf("webview2 runtime not installed")
+ }
+ installedCorrectly, err := webview2runtime.InstallUsingEmbeddedBootstrapper()
+ if err != nil {
+ _ = webview2runtime.Error(err.Error(), "Error")
+ return err
+ }
+ if !installedCorrectly {
+ err = webview2runtime.Error("The runtime failed to install correctly. Please try again.", "Error")
+ return err
+ }
+ return nil
+}
diff --git a/v2/internal/ffenestri/windows/wv2runtime/error.go b/v2/internal/ffenestri/windows/wv2runtime/error.go
new file mode 100644
index 000000000..f03d8c81c
--- /dev/null
+++ b/v2/internal/ffenestri/windows/wv2runtime/error.go
@@ -0,0 +1,13 @@
+// +build wv2runtime.error
+
+package wv2runtime
+
+import (
+ "fmt"
+ "github.com/leaanthony/webview2runtime"
+)
+
+func doInstallationStrategy(installStatus installationStatus) error {
+ _ = webview2runtime.Error("The WebView2 runtime is required to run this application. Please contact your system administrator.", "Error")
+ return fmt.Errorf("webview2 runtime not installed")
+}
diff --git a/v2/internal/ffenestri/windows/wv2runtime/wv2runtime.go b/v2/internal/ffenestri/windows/wv2runtime/wv2runtime.go
new file mode 100644
index 000000000..7326d54b1
--- /dev/null
+++ b/v2/internal/ffenestri/windows/wv2runtime/wv2runtime.go
@@ -0,0 +1,35 @@
+package wv2runtime
+
+import (
+ "github.com/leaanthony/go-webview2/webviewloader"
+ "github.com/leaanthony/webview2runtime"
+)
+
+const MinimumRuntimeVersion string = "91.0.992.28"
+
+type installationStatus int
+
+const (
+ needsInstalling installationStatus = iota
+ needsUpdating
+ installed
+)
+
+func Process() (*webview2runtime.Info, error) {
+ installStatus := needsInstalling
+ installedVersion := webview2runtime.GetInstalledVersion()
+ if installedVersion != nil {
+ installStatus = installed
+ compareResult, err := webviewloader.CompareBrowserVersions(installedVersion.Version, MinimumRuntimeVersion)
+ if err != nil {
+ return nil, err
+ }
+ updateRequired := compareResult == -1
+ // Installed and does not require updating
+ if !updateRequired {
+ return installedVersion, nil
+ }
+
+ }
+ return installedVersion, doInstallationStrategy(installStatus)
+}
diff --git a/v2/internal/ffenestri/windows/x64/WebView2Loader.dll b/v2/internal/ffenestri/windows/x64/WebView2Loader.dll
new file mode 100644
index 000000000..869459eca
Binary files /dev/null and b/v2/internal/ffenestri/windows/x64/WebView2Loader.dll differ
diff --git a/v2/internal/ffenestri/windows/x64/x64.go b/v2/internal/ffenestri/windows/x64/x64.go
new file mode 100644
index 000000000..8e4e2f31b
--- /dev/null
+++ b/v2/internal/ffenestri/windows/x64/x64.go
@@ -0,0 +1,8 @@
+// +build windows
+
+package x64
+
+import _ "embed"
+
+//go:embed WebView2Loader.dll
+var WebView2Loader []byte
diff --git a/v2/internal/ffenestri/windows_checkboxes.go b/v2/internal/ffenestri/windows_checkboxes.go
new file mode 100644
index 000000000..e76dfa8ca
--- /dev/null
+++ b/v2/internal/ffenestri/windows_checkboxes.go
@@ -0,0 +1,93 @@
+//+build windows
+
+package ffenestri
+
+import (
+ "fmt"
+ "github.com/leaanthony/slicer"
+ "github.com/wailsapp/wails/v2/internal/menumanager"
+ "os"
+ "sync"
+ "text/tabwriter"
+)
+
+/* ---------------------------------------------------------------------------------
+
+Checkbox Cache
+--------------
+The checkbox cache keeps a list of IDs that are associated with the same checkbox menu item.
+This can happen when a checkbox is used in an application menu and a tray menu, eg "start at login".
+The cache is used to bulk toggle the menu items when one is clicked.
+
+*/
+
+type CheckboxCache struct {
+ cache map[*menumanager.ProcessedMenu]map[wailsMenuItemID][]win32MenuItemID
+ mutex sync.RWMutex
+}
+
+func NewCheckboxCache() *CheckboxCache {
+ return &CheckboxCache{
+ cache: make(map[*menumanager.ProcessedMenu]map[wailsMenuItemID][]win32MenuItemID),
+ }
+}
+
+func (c *CheckboxCache) Dump() {
+ // Start a new tabwriter
+ w := new(tabwriter.Writer)
+ w.Init(os.Stdout, 8, 8, 0, '\t', 0)
+
+ println("---------------- Checkbox", c, "Dump ----------------")
+ for _, processedMenu := range c.cache {
+ println("Menu", processedMenu)
+ for wailsMenuItemID, win32menus := range processedMenu {
+ println(" WailsMenu: ", wailsMenuItemID)
+ menus := slicer.String()
+ for _, win32menu := range win32menus {
+ menus.Add(fmt.Sprintf("%v", win32menu))
+ }
+ _, _ = fmt.Fprintf(w, "%s\t%s\n", wailsMenuItemID, menus.Join(", "))
+ _ = w.Flush()
+ }
+ }
+}
+
+func (c *CheckboxCache) addToCheckboxCache(menu *menumanager.ProcessedMenu, item wailsMenuItemID, menuID win32MenuItemID) {
+
+ // Get map for menu
+ if c.cache[menu] == nil {
+ c.cache[menu] = make(map[wailsMenuItemID][]win32MenuItemID)
+ }
+ menuMap := c.cache[menu]
+
+ // Ensure we have a slice
+ if menuMap[item] == nil {
+ menuMap[item] = []win32MenuItemID{}
+ }
+
+ c.mutex.Lock()
+ menuMap[item] = append(menuMap[item], menuID)
+ c.mutex.Unlock()
+
+}
+
+func (c *CheckboxCache) removeMenuFromCheckboxCache(menu *menumanager.ProcessedMenu) {
+ c.mutex.Lock()
+ delete(c.cache, menu)
+ c.mutex.Unlock()
+}
+
+// win32MenuIDsForWailsMenuID returns all win32menuids that are used for a wails menu item id across
+// all menus
+func (c *CheckboxCache) win32MenuIDsForWailsMenuID(item wailsMenuItemID) []win32MenuItemID {
+ c.mutex.Lock()
+ result := []win32MenuItemID{}
+ for _, menu := range c.cache {
+ ids := menu[item]
+ if ids != nil {
+ result = append(result, ids...)
+ }
+ }
+ c.mutex.Unlock()
+ return result
+}
diff --git a/v2/internal/ffenestri/windows_errorhandler_debug.go b/v2/internal/ffenestri/windows_errorhandler_debug.go
new file mode 100644
index 000000000..5de8758b6
--- /dev/null
+++ b/v2/internal/ffenestri/windows_errorhandler_debug.go
@@ -0,0 +1,28 @@
+//+build windows,debug
+
+package ffenestri
+
+import (
+ "fmt"
+ "github.com/ztrue/tracerr"
+ "runtime"
+ "strings"
+)
+
+func wall(err error, inputs ...interface{}) error {
+ if err == nil {
+ return nil
+ }
+ pc, _, _, _ := runtime.Caller(1)
+ funcName := runtime.FuncForPC(pc).Name()
+ splitName := strings.Split(funcName, ".")
+ message := "[" + splitName[len(splitName)-1] + "]"
+ if len(inputs) > 0 {
+ params := []string{}
+ for _, param := range inputs {
+ params = append(params, fmt.Sprintf("%v", param))
+ }
+ message += "(" + strings.Join(params, " ") + ")"
+ }
+ return tracerr.Errorf(message)
+}
diff --git a/v2/internal/ffenestri/windows_errorhandler_production.go b/v2/internal/ffenestri/windows_errorhandler_production.go
new file mode 100644
index 000000000..20c9dc9d8
--- /dev/null
+++ b/v2/internal/ffenestri/windows_errorhandler_production.go
@@ -0,0 +1,47 @@
+// +build windows,!debug
+
+package ffenestri
+
+import "C"
+import (
+ "fmt"
+ "golang.org/x/sys/windows"
+ "log"
+ "os"
+ "runtime"
+ "strings"
+ "syscall"
+)
+
+func wall(err error, inputs ...interface{}) error {
+ if err == nil {
+ return nil
+ }
+ pc, _, _, _ := runtime.Caller(1)
+ funcName := runtime.FuncForPC(pc).Name()
+ splitName := strings.Split(funcName, ".")
+ message := "[" + splitName[len(splitName)-1] + "]"
+ if len(inputs) > 0 {
+ params := []string{}
+ for _, param := range inputs {
+ params = append(params, fmt.Sprintf("%v", param))
+ }
+ message += "(" + strings.Join(params, " ") + ")"
+ }
+
+ title, err := syscall.UTF16PtrFromString("Fatal Error")
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ text, err := syscall.UTF16PtrFromString("There has been a fatal error. Details:\n" + message)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ var flags uint32 = windows.MB_ICONERROR | windows.MB_OK
+
+ _, err = windows.MessageBox(0, text, title, flags|windows.MB_SYSTEMMODAL)
+ os.Exit(1)
+ return err
+}
diff --git a/v2/internal/ffenestri/windows_menu.go b/v2/internal/ffenestri/windows_menu.go
new file mode 100644
index 000000000..384ffb7fe
--- /dev/null
+++ b/v2/internal/ffenestri/windows_menu.go
@@ -0,0 +1,232 @@
+//+build windows
+
+package ffenestri
+
+import (
+ "fmt"
+ "github.com/wailsapp/wails/v2/internal/menumanager"
+ "github.com/wailsapp/wails/v2/pkg/menu"
+ "github.com/wailsapp/wails/v2/pkg/menu/keys"
+ "runtime"
+ "strings"
+)
+
+//-------------------- Types ------------------------
+
+type win32MenuItemID uint32
+type win32Menu uintptr
+type win32Window uintptr
+type wailsMenuItemID string // The internal menu ID
+
+type Menu struct {
+ wailsMenu *menumanager.WailsMenu
+ menu win32Menu
+ menuType menuType
+
+ // A list of all checkbox and radio menuitems we
+ // create for this menu
+ checkboxes []win32MenuItemID
+ radioboxes []win32MenuItemID
+ initiallySelectedRadioItems []win32MenuItemID
+}
+
+func createMenu(wailsMenu *menumanager.WailsMenu, menuType menuType) (*Menu, error) {
+
+ mainMenu, err := createWin32Menu()
+ if err != nil {
+ return nil, err
+ }
+
+ result := &Menu{
+ wailsMenu: wailsMenu,
+ menu: mainMenu,
+ menuType: menuType,
+ }
+
+ // Process top level menus
+ for _, toplevelmenu := range applicationMenu.Menu.Items {
+ err := result.processMenuItem(result.menu, toplevelmenu)
+ if err != nil {
+ return nil, err
+ }
+ }
+
+ err = result.processRadioGroups()
+ if err != nil {
+ return nil, err
+ }
+
+ return result, nil
+}
+
+func (m *Menu) processMenuItem(parent win32Menu, menuItem *menumanager.ProcessedMenuItem) error {
+
+ // Ignore hidden items
+ if menuItem.Hidden {
+ return nil
+ }
+
+ // Calculate the flags for this menu item
+ flags := uintptr(calculateFlags(menuItem))
+
+ switch menuItem.Type {
+ case menu.SubmenuType:
+ submenu, err := createWin32PopupMenu()
+ if err != nil {
+ return err
+ }
+ for _, submenuItem := range menuItem.SubMenu.Items {
+ err = m.processMenuItem(submenu, submenuItem)
+ if err != nil {
+ return err
+ }
+ }
+ err = appendWin32MenuItem(parent, flags, uintptr(submenu), menuItem.Label)
+ if err != nil {
+ return err
+ }
+ case menu.TextType, menu.CheckboxType, menu.RadioType:
+ win32ID := addMenuCacheEntry(parent, m.menuType, menuItem, m.wailsMenu.Menu)
+ if menuItem.Accelerator != nil {
+ m.processAccelerator(menuItem)
+ }
+ label := menuItem.Label
+ //label := fmt.Sprintf("%s (%d)", menuItem.Label, win32ID)
+ err := appendWin32MenuItem(parent, flags, uintptr(win32ID), label)
+ if err != nil {
+ return err
+ }
+ if menuItem.Type == menu.CheckboxType {
+ // We need to maintain a list of this menu's checkboxes
+ m.checkboxes = append(m.checkboxes, win32ID)
+ globalCheckboxCache.addToCheckboxCache(m.wailsMenu.Menu, wailsMenuItemID(menuItem.ID), win32ID)
+ }
+ if menuItem.Type == menu.RadioType {
+ // We need to maintain a list of this menu's radioitems
+ m.radioboxes = append(m.radioboxes, win32ID)
+ globalRadioGroupMap.addRadioGroupMapping(m.wailsMenu.Menu, wailsMenuItemID(menuItem.ID), win32ID)
+ if menuItem.Checked {
+ m.initiallySelectedRadioItems = append(m.initiallySelectedRadioItems, win32ID)
+ }
+ }
+ case menu.SeparatorType:
+ err := appendWin32MenuItem(parent, flags, 0, "")
+ if err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+func (m *Menu) processRadioGroups() error {
+
+ for _, rg := range applicationMenu.RadioGroups {
+ startWailsMenuID := wailsMenuItemID(rg.Members[0])
+ endWailsMenuID := wailsMenuItemID(rg.Members[len(rg.Members)-1])
+
+ startIDs := globalRadioGroupMap.getRadioGroupMapping(startWailsMenuID)
+ endIDs := globalRadioGroupMap.getRadioGroupMapping(endWailsMenuID)
+
+ var radioGroupMaps = []*radioGroupStartEnd{}
+ for index := range startIDs {
+ startID := startIDs[index]
+ endID := endIDs[index]
+ thisRadioGroup := &radioGroupStartEnd{
+ startID: startID,
+ endID: endID,
+ }
+ radioGroupMaps = append(radioGroupMaps, thisRadioGroup)
+ }
+
+ // Set this for each member
+ for _, member := range rg.Members {
+ id := wailsMenuItemID(member)
+ globalRadioGroupCache.addToRadioGroupCache(m.wailsMenu.Menu, id, radioGroupMaps)
+ }
+ }
+
+ // Enable all initially checked radio items
+ for _, win32MenuID := range m.initiallySelectedRadioItems {
+ menuItemDetails := getMenuCacheEntry(win32MenuID)
+ wailsMenuID := wailsMenuItemID(menuItemDetails.item.ID)
+ err := selectRadioItemFromWailsMenuID(wailsMenuID, win32MenuID)
+ if err != nil {
+ return err
+ }
+ }
+
+ return nil
+}
+
+func (m *Menu) Destroy() error {
+
+ // Release the MenuIDs
+ releaseMenuIDsForProcessedMenu(m.wailsMenu.Menu)
+
+ // Unload this menu's checkboxes from the cache
+ globalCheckboxCache.removeMenuFromCheckboxCache(m.wailsMenu.Menu)
+
+ // Unload this menu's radio groups from the cache
+ globalRadioGroupCache.removeMenuFromRadioBoxCache(m.wailsMenu.Menu)
+
+ globalRadioGroupMap.removeMenuFromRadioGroupMapping(m.wailsMenu.Menu)
+
+ // Free up callbacks
+ resetCallbacks()
+
+ // Delete menu
+ return destroyWin32Menu(m.menu)
+}
+
+func (m *Menu) processAccelerator(menuitem *menumanager.ProcessedMenuItem) {
+
+ // Add in shortcut to label if there is no "\t" override
+ if !strings.Contains(menuitem.Label, "\t") {
+ menuitem.Label += "\t" + keys.Stringify(menuitem.Accelerator, runtime.GOOS)
+ }
+
+ // Calculate the modifier
+ var modifiers uint8
+ for _, mod := range menuitem.Accelerator.Modifiers {
+ switch mod {
+ case keys.ControlKey, keys.CmdOrCtrlKey:
+ modifiers |= 1
+ case keys.OptionOrAltKey:
+ modifiers |= 2
+ case keys.ShiftKey:
+ modifiers |= 4
+ //case keys.SuperKey:
+ // modifiers |= 8
+ }
+ }
+
+ var keycode = calculateKeycode(strings.ToLower(menuitem.Accelerator.Key))
+ if keycode == 0 {
+ fmt.Printf("WARNING: Key '%s' is unsupported in windows. Cannot bind callback.", menuitem.Accelerator.Key)
+ return
+ }
+ addMenuCallback(keycode, modifiers, menuitem.ID, m.menuType)
+
+}
+
+var flagMap = map[menu.Type]uint32{
+ menu.TextType: MF_STRING,
+ menu.SeparatorType: MF_SEPARATOR,
+ menu.SubmenuType: MF_STRING | MF_POPUP,
+ menu.CheckboxType: MF_STRING,
+ menu.RadioType: MF_STRING,
+}
+
+func calculateFlags(menuItem *menumanager.ProcessedMenuItem) uint32 {
+ result := flagMap[menuItem.Type]
+
+ if menuItem.Disabled {
+ result |= MF_DISABLED
+ }
+
+ if menuItem.Type == menu.CheckboxType && menuItem.Checked {
+ result |= MF_CHECKED
+ }
+
+ return result
+}
diff --git a/v2/internal/ffenestri/windows_menu_cache.go b/v2/internal/ffenestri/windows_menu_cache.go
new file mode 100644
index 000000000..5b6762d9b
--- /dev/null
+++ b/v2/internal/ffenestri/windows_menu_cache.go
@@ -0,0 +1,74 @@
+//+build windows
+
+package ffenestri
+
+import (
+ "github.com/leaanthony/idgen"
+ "github.com/wailsapp/wails/v2/internal/menumanager"
+ "sync"
+)
+
+/**
+
+MenuCache
+---------
+When windows calls back to Go (when an item is clicked), we need to
+be able to retrieve information about the menu item:
+ - The menu that the menuitem is part of (parent)
+ - The original processed menu item
+ - The type of the menu (application, context or tray)
+
+This cache is built up when a menu is created.
+
+*/
+
+// TODO: Make this like the other caches
+
+type menuCacheEntry struct {
+ parent win32Menu
+ menuType menuType
+ item *menumanager.ProcessedMenuItem
+ processedMenu *menumanager.ProcessedMenu
+}
+
+var idGenerator = idgen.New()
+
+var menuCache = map[win32MenuItemID]*menuCacheEntry{}
+var menuCacheLock sync.RWMutex
+var wailsMenuIDtoWin32IDMap = map[wailsMenuItemID]win32MenuItemID{}
+
+// This releases the menuIDs back to the id generator
+var winIDsOwnedByProcessedMenu = map[*menumanager.ProcessedMenu][]win32MenuItemID{}
+
+func releaseMenuIDsForProcessedMenu(processedMenu *menumanager.ProcessedMenu) {
+ for _, menuID := range winIDsOwnedByProcessedMenu[processedMenu] {
+ idGenerator.ReleaseID(uint(menuID))
+ }
+ delete(winIDsOwnedByProcessedMenu, processedMenu)
+}
+
+func addMenuCacheEntry(parent win32Menu, typ menuType, wailsMenuItem *menumanager.ProcessedMenuItem, processedMenu *menumanager.ProcessedMenu) win32MenuItemID {
+ menuCacheLock.Lock()
+ defer menuCacheLock.Unlock()
+ id, err := idGenerator.NewID()
+ checkFatal(err)
+ menuID := win32MenuItemID(id)
+ menuCache[menuID] = &menuCacheEntry{
+ parent: parent,
+ menuType: typ,
+ item: wailsMenuItem,
+ processedMenu: processedMenu,
+ }
+ // save the mapping
+ wailsMenuIDtoWin32IDMap[wailsMenuItemID(wailsMenuItem.ID)] = menuID
+ // keep track of menuids owned by this menu (so we can release the ids)
+ winIDsOwnedByProcessedMenu[processedMenu] = append(winIDsOwnedByProcessedMenu[processedMenu], menuID)
+ return menuID
+
+}
+
+func getMenuCacheEntry(id win32MenuItemID) *menuCacheEntry {
+ menuCacheLock.Lock()
+ defer menuCacheLock.Unlock()
+ return menuCache[id]
+}
diff --git a/v2/internal/ffenestri/windows_menu_callbacks.go b/v2/internal/ffenestri/windows_menu_callbacks.go
new file mode 100644
index 000000000..9bfae895b
--- /dev/null
+++ b/v2/internal/ffenestri/windows_menu_callbacks.go
@@ -0,0 +1,126 @@
+package ffenestri
+
+type callbackData struct {
+ menuID string
+ menuType menuType
+}
+
+var callbacks = map[uint16]map[uint8]callbackData{}
+
+func addMenuCallback(key uint16, modifiers uint8, menuID string, menutype menuType) {
+
+ if callbacks[key] == nil {
+ callbacks[key] = make(map[uint8]callbackData)
+ }
+ callbacks[key][modifiers] = callbackData{
+ menuID: menuID,
+ menuType: menutype,
+ }
+}
+
+func resetCallbacks() {
+ callbacks = map[uint16]map[uint8]callbackData{}
+}
+
+func getCallbackForKeyPress(key uint16, modifiers uint8) (string, menuType) {
+ if callbacks[key] == nil {
+ return "", ""
+ }
+ result := callbacks[key][modifiers]
+ return result.menuID, result.menuType
+}
+
+func calculateKeycode(key string) uint16 {
+ return keymap[key]
+}
+
+// TODO: Complete this list
+var keymap = map[string]uint16{
+ "0": 0x30,
+ "1": 0x31,
+ "2": 0x32,
+ "3": 0x33,
+ "4": 0x34,
+ "5": 0x35,
+ "6": 0x36,
+ "7": 0x37,
+ "8": 0x38,
+ "9": 0x39,
+ "a": 0x41,
+ "b": 0x42,
+ "c": 0x43,
+ "d": 0x44,
+ "e": 0x45,
+ "f": 0x46,
+ "g": 0x47,
+ "h": 0x48,
+ "i": 0x49,
+ "j": 0x4A,
+ "k": 0x4B,
+ "l": 0x4C,
+ "m": 0x4D,
+ "n": 0x4E,
+ "o": 0x4F,
+ "p": 0x50,
+ "q": 0x51,
+ "r": 0x52,
+ "s": 0x53,
+ "t": 0x54,
+ "u": 0x55,
+ "v": 0x56,
+ "w": 0x57,
+ "x": 0x58,
+ "y": 0x59,
+ "z": 0x5A,
+ "backspace": 0x08,
+ "tab": 0x09,
+ "return": 0x0D,
+ "enter": 0x0D,
+ "escape": 0x1B,
+ "left": 0x25,
+ "right": 0x27,
+ "up": 0x26,
+ "down": 0x28,
+ "space": 0x20,
+ "delete": 0x2E,
+ "home": 0x24,
+ "end": 0x23,
+ "page up": 0x21,
+ "page down": 0x22,
+ "f1": 0x70,
+ "f2": 0x71,
+ "f3": 0x72,
+ "f4": 0x73,
+ "f5": 0x74,
+ "f6": 0x75,
+ "f7": 0x76,
+ "f8": 0x77,
+ "f9": 0x78,
+ "f10": 0x79,
+ "f11": 0x7A,
+ "f12": 0x7B,
+ "f13": 0x7C,
+ "f14": 0x7D,
+ "f15": 0x7E,
+ "f16": 0x7F,
+ "f17": 0x80,
+ "f18": 0x81,
+ "f19": 0x82,
+ "f20": 0x83,
+ "f21": 0x84,
+ "f22": 0x85,
+ "f23": 0x86,
+ "f24": 0x87,
+ // Windows doesn't have these apparently so use 0 for unsupported
+ "f25": 0,
+ "f26": 0,
+ "f27": 0,
+ "f28": 0,
+ "f29": 0,
+ "f30": 0,
+ "f31": 0,
+ "f32": 0,
+ "f33": 0,
+ "f34": 0,
+ "f35": 0,
+}
diff --git a/v2/internal/ffenestri/windows_radiogroup.go b/v2/internal/ffenestri/windows_radiogroup.go
new file mode 100644
index 000000000..3f3d349ff
--- /dev/null
+++ b/v2/internal/ffenestri/windows_radiogroup.go
@@ -0,0 +1,194 @@
+//+build windows
+
+package ffenestri
+
+import (
+ "fmt"
+ "github.com/leaanthony/slicer"
+ "os"
+ "sync"
+ "text/tabwriter"
+
+ "github.com/wailsapp/wails/v2/internal/menumanager"
+)
+
+/* ---------------------------------------------------------------------------------
+
+Radio Groups
+------------
+Radio groups are stored by the ProcessedMenu as a list of menu ids.
+Windows only cares about the start and end ids of the group so we
+preprocess the radio groups and store this data in a radioGroupMap.
+When a radio button is clicked, we use the menu id to read in the
+radio group data and call CheckMenuRadioItem to update the group.
+
+*/
+
+type radioGroupStartEnd struct {
+ startID win32MenuItemID
+ endID win32MenuItemID
+}
+
+type RadioGroupCache struct {
+ cache map[*menumanager.ProcessedMenu]map[wailsMenuItemID][]*radioGroupStartEnd
+ mutex sync.RWMutex
+}
+
+func NewRadioGroupCache() *RadioGroupCache {
+ return &RadioGroupCache{
+ cache: make(map[*menumanager.ProcessedMenu]map[wailsMenuItemID][]*radioGroupStartEnd),
+ }
+}
+
+func (c *RadioGroupCache) Dump() {
+ // Start a new tabwriter
+ w := new(tabwriter.Writer)
+ w.Init(os.Stdout, 8, 8, 0, '\t', 0)
+
+ println("---------------- RadioGroupCache", c, "Dump ----------------")
+ for menu, processedMenu := range c.cache {
+ println("Menu", menu)
+ _, _ = fmt.Fprintf(w, "Wails ID \tWindows ID Pairs\n")
+ for wailsMenuItemID, radioGroupStartEnd := range processedMenu {
+ menus := slicer.String()
+ for _, se := range radioGroupStartEnd {
+ menus.Add(fmt.Sprintf("[%d -> %d]", se.startID, se.endID))
+ }
+ _, _ = fmt.Fprintf(w, "%s\t%s\n", wailsMenuItemID, menus.Join(", "))
+ _ = w.Flush()
+ }
+ }
+}
+
+func (c *RadioGroupCache) addToRadioGroupCache(menu *menumanager.ProcessedMenu, item wailsMenuItemID, radioGroupMaps []*radioGroupStartEnd) {
+
+ c.mutex.Lock()
+
+ // Get map for menu
+ if c.cache[menu] == nil {
+ c.cache[menu] = make(map[wailsMenuItemID][]*radioGroupStartEnd)
+ }
+ menuMap := c.cache[menu]
+
+ // Ensure we have a slice
+ if menuMap[item] == nil {
+ menuMap[item] = []*radioGroupStartEnd{}
+ }
+
+ menuMap[item] = radioGroupMaps
+
+ c.mutex.Unlock()
+
+}
+
+func (c *RadioGroupCache) removeMenuFromRadioBoxCache(menu *menumanager.ProcessedMenu) {
+ c.mutex.Lock()
+ delete(c.cache, menu)
+ c.mutex.Unlock()
+}
+
+func (c *RadioGroupCache) getRadioGroupMappings(wailsMenuID wailsMenuItemID) []*radioGroupStartEnd {
+ c.mutex.Lock()
+ result := []*radioGroupStartEnd{}
+ for _, menugroups := range c.cache {
+ groups := menugroups[wailsMenuID]
+ if groups != nil {
+ result = append(result, groups...)
+ }
+ }
+ c.mutex.Unlock()
+ return result
+}
+
+type RadioGroupMap struct {
+ cache map[*menumanager.ProcessedMenu]map[wailsMenuItemID][]win32MenuItemID
+ mutex sync.RWMutex
+}
+
+func NewRadioGroupMap() *RadioGroupMap {
+ return &RadioGroupMap{
+ cache: make(map[*menumanager.ProcessedMenu]map[wailsMenuItemID][]win32MenuItemID),
+ }
+}
+
+func (c *RadioGroupMap) Dump() {
+ // Start a new tabwriter
+ w := new(tabwriter.Writer)
+ w.Init(os.Stdout, 8, 8, 0, '\t', 0)
+
+ println("---------------- RadioGroupMap", c, "Dump ----------------")
+ for _, processedMenu := range c.cache {
+ _, _ = fmt.Fprintf(w, "Menu\tWails ID \tWindows IDs\n")
+ for wailsMenuItemID, win32menus := range processedMenu {
+ menus := slicer.String()
+ for _, win32menu := range win32menus {
+ menus.Add(fmt.Sprintf("%v", win32menu))
+ }
+ _, _ = fmt.Fprintf(w, "%p\t%s\t%s\n", processedMenu, wailsMenuItemID, menus.Join(", "))
+ _ = w.Flush()
+ }
+ }
+}
+
+func (m *RadioGroupMap) addRadioGroupMapping(menu *menumanager.ProcessedMenu, item wailsMenuItemID, win32ID win32MenuItemID) {
+ m.mutex.Lock()
+
+ // Get map for menu
+ if m.cache[menu] == nil {
+ m.cache[menu] = make(map[wailsMenuItemID][]win32MenuItemID)
+ }
+ menuMap := m.cache[menu]
+
+ // Ensure we have a slice
+ if menuMap[item] == nil {
+ menuMap[item] = []win32MenuItemID{}
+ }
+
+ menuMap[item] = append(menuMap[item], win32ID)
+
+ m.mutex.Unlock()
+}
+
+func (m *RadioGroupMap) removeMenuFromRadioGroupMapping(menu *menumanager.ProcessedMenu) {
+ m.mutex.Lock()
+ delete(m.cache, menu)
+ m.mutex.Unlock()
+}
+
+func (m *RadioGroupMap) getRadioGroupMapping(wailsMenuID wailsMenuItemID) []win32MenuItemID {
+ m.mutex.Lock()
+ result := []win32MenuItemID{}
+ for _, menuids := range m.cache {
+ ids := menuids[wailsMenuID]
+ if ids != nil {
+ result = append(result, ids...)
+ }
+ }
+ m.mutex.Unlock()
+ return result
+}
+
+func selectRadioItemFromWailsMenuID(wailsMenuID wailsMenuItemID, win32MenuID win32MenuItemID) error {
+ radioItemGroups := globalRadioGroupCache.getRadioGroupMappings(wailsMenuID)
+ // Figure out offset into group
+ var offset win32MenuItemID = 0
+ for _, radioItemGroup := range radioItemGroups {
+ if win32MenuID >= radioItemGroup.startID && win32MenuID <= radioItemGroup.endID {
+ offset = win32MenuID - radioItemGroup.startID
+ break
+ }
+ }
+ for _, radioItemGroup := range radioItemGroups {
+ selectedMenuID := radioItemGroup.startID + offset
+ menuItemDetails := getMenuCacheEntry(selectedMenuID)
+ if menuItemDetails != nil {
+ if menuItemDetails.parent != 0 {
+ err := selectRadioItem(selectedMenuID, radioItemGroup.startID, radioItemGroup.endID, menuItemDetails.parent)
+ if err != nil {
+ return err
+ }
+ }
+ }
+ }
+ return nil
+}
diff --git a/v2/internal/ffenestri/windows_win32.go b/v2/internal/ffenestri/windows_win32.go
new file mode 100644
index 000000000..5942b9bcf
--- /dev/null
+++ b/v2/internal/ffenestri/windows_win32.go
@@ -0,0 +1,130 @@
+//+build windows
+
+package ffenestri
+
+import (
+ "unsafe"
+
+ "github.com/wailsapp/wails/v2/internal/menumanager"
+ "golang.org/x/sys/windows"
+)
+
+var (
+ // DLL stuff
+ user32 = windows.NewLazySystemDLL("User32.dll")
+ win32CreateMenu = user32.NewProc("CreateMenu")
+ win32DestroyMenu = user32.NewProc("DestroyMenu")
+ win32CreatePopupMenu = user32.NewProc("CreatePopupMenu")
+ win32AppendMenuW = user32.NewProc("AppendMenuW")
+ win32SetMenu = user32.NewProc("SetMenu")
+ win32CheckMenuItem = user32.NewProc("CheckMenuItem")
+ win32GetMenuState = user32.NewProc("GetMenuState")
+ win32CheckMenuRadioItem = user32.NewProc("CheckMenuRadioItem")
+
+ applicationMenu *menumanager.WailsMenu
+ menuManager *menumanager.Manager
+)
+
+const MF_BITMAP uint32 = 0x00000004
+const MF_CHECKED uint32 = 0x00000008
+const MF_DISABLED uint32 = 0x00000002
+const MF_ENABLED uint32 = 0x00000000
+const MF_GRAYED uint32 = 0x00000001
+const MF_MENUBARBREAK uint32 = 0x00000020
+const MF_MENUBREAK uint32 = 0x00000040
+const MF_OWNERDRAW uint32 = 0x00000100
+const MF_POPUP uint32 = 0x00000010
+const MF_SEPARATOR uint32 = 0x00000800
+const MF_STRING uint32 = 0x00000000
+const MF_UNCHECKED uint32 = 0x00000000
+const MF_BYCOMMAND uint32 = 0x00000000
+const MF_BYPOSITION uint32 = 0x00000400
+
+const WM_SIZE = 5
+const WM_GETMINMAXINFO = 36
+
+type Win32Rect struct {
+ Left int32
+ Top int32
+ Right int32
+ Bottom int32
+}
+
+// ------------------- win32 calls -----------------------
+
+func createWin32Menu() (win32Menu, error) {
+ res, _, err := win32CreateMenu.Call()
+ if res == 0 {
+ return 0, wall(err)
+ }
+ return win32Menu(res), nil
+}
+
+func destroyWin32Menu(menu win32Menu) error {
+ res, _, err := win32DestroyMenu.Call(uintptr(menu))
+ if res == 0 {
+ return wall(err, "Menu:", menu)
+ }
+ return nil
+}
+
+func createWin32PopupMenu() (win32Menu, error) {
+ res, _, err := win32CreatePopupMenu.Call()
+ if res == 0 {
+ return 0, wall(err)
+ }
+ return win32Menu(res), nil
+}
+
+func appendWin32MenuItem(menu win32Menu, flags uintptr, submenuOrID uintptr, label string) error {
+ menuText, err := windows.UTF16PtrFromString(label)
+ if err != nil {
+ return err
+ }
+ res, _, err := win32AppendMenuW.Call(
+ uintptr(menu),
+ flags,
+ submenuOrID,
+ uintptr(unsafe.Pointer(menuText)),
+ )
+ if res == 0 {
+ return wall(err, "Menu", menu, "Flags", flags, "submenuOrID", submenuOrID, "label", label)
+ }
+ return nil
+}
+
+func setWindowMenu(window win32Window, menu win32Menu) error {
+ res, _, err := win32SetMenu.Call(uintptr(window), uintptr(menu))
+ if res == 0 {
+ return wall(err, "window", window, "menu", menu)
+ }
+ return nil
+}
+
+func selectRadioItem(selectedMenuID, startMenuItemID, endMenuItemID win32MenuItemID, parent win32Menu) error {
+ res, _, err := win32CheckMenuRadioItem.Call(uintptr(parent), uintptr(startMenuItemID), uintptr(endMenuItemID), uintptr(selectedMenuID), uintptr(MF_BYCOMMAND))
+ if int(res) == 0 {
+ return wall(err, selectedMenuID, startMenuItemID, endMenuItemID, parent)
+ }
+ return nil
+}
+
+//
+//func getWindowRect(window win32Window) (*Win32Rect, error) {
+// var windowRect Win32Rect
+// res, _, err := win32GetWindowRect.Call(uintptr(window), uintptr(unsafe.Pointer(&windowRect)))
+// if res == 0 {
+// return nil, err
+// }
+// return &windowRect, nil
+//}
+//
+//func getClientRect(window win32Window) (*Win32Rect, error) {
+// var clientRect Win32Rect
+// res, _, err := win32GetClientRect.Call(uintptr(window), uintptr(unsafe.Pointer(&clientRect)))
+// if res == 0 {
+// return nil, err
+// }
+// return &clientRect, nil
+//}
+//
diff --git a/v2/internal/ffenestri/wv2ComHandler_windows.h b/v2/internal/ffenestri/wv2ComHandler_windows.h
new file mode 100644
index 000000000..60fc43574
--- /dev/null
+++ b/v2/internal/ffenestri/wv2ComHandler_windows.h
@@ -0,0 +1,126 @@
+
+#ifndef WV2COMHANDLER_H
+#define WV2COMHANDLER_H
+
+#include "ffenestri_windows.h"
+#include "windows/WebView2.h"
+
+#include
+#include
+
+class wv2ComHandler
+ : public ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler,
+ public ICoreWebView2CreateCoreWebView2ControllerCompletedHandler,
+ public ICoreWebView2WebMessageReceivedEventHandler,
+ public ICoreWebView2PermissionRequestedEventHandler,
+ public ICoreWebView2AcceleratorKeyPressedEventHandler
+{
+
+ struct Application *app;
+ HWND window;
+ messageCallback mcb;
+ comHandlerCallback cb;
+
+ public:
+ wv2ComHandler(struct Application *app, HWND window, messageCallback mcb, comHandlerCallback cb) {
+ this->app = app;
+ this->window = window;
+ this->mcb = mcb;
+ this->cb = cb;
+ }
+ ULONG STDMETHODCALLTYPE AddRef() { return 1; }
+ ULONG STDMETHODCALLTYPE Release() { return 1; }
+ HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, LPVOID *ppv) {
+ return S_OK;
+ }
+ HRESULT STDMETHODCALLTYPE Invoke(HRESULT res,
+ ICoreWebView2Environment *env) {
+ env->CreateCoreWebView2Controller(window, this);
+ return S_OK;
+ }
+ HRESULT STDMETHODCALLTYPE Invoke(HRESULT res,
+ ICoreWebView2Controller *controller) {
+ controller->AddRef();
+
+ ICoreWebView2 *webview;
+ ::EventRegistrationToken token;
+ controller->get_CoreWebView2(&webview);
+ controller->add_AcceleratorKeyPressed(this, &token);
+ webview->add_WebMessageReceived(this, &token);
+ webview->add_PermissionRequested(this, &token);
+
+ cb(controller);
+ return S_OK;
+ }
+
+ // This is our keyboard callback method
+ HRESULT STDMETHODCALLTYPE Invoke(ICoreWebView2Controller *controller, ICoreWebView2AcceleratorKeyPressedEventArgs * args) {
+ // Prevent WebView2 from processing the key
+ args->put_Handled(TRUE);
+
+ COREWEBVIEW2_KEY_EVENT_KIND kind;
+ args->get_KeyEventKind(&kind);
+ if (kind == COREWEBVIEW2_KEY_EVENT_KIND_KEY_DOWN ||
+ kind == COREWEBVIEW2_KEY_EVENT_KIND_SYSTEM_KEY_DOWN)
+ {
+ UINT key;
+ args->get_VirtualKey(&key);
+ COREWEBVIEW2_PHYSICAL_KEY_STATUS status;
+ args->get_PhysicalKeyStatus(&status);
+ if (!status.WasKeyDown)
+ {
+ processKeyPress(key);
+ }
+ }
+ return S_OK;
+ }
+
+ // This is called when JS posts a message back to webkit
+ HRESULT STDMETHODCALLTYPE Invoke(
+ ICoreWebView2 *sender, ICoreWebView2WebMessageReceivedEventArgs *args) {
+ LPWSTR message;
+ args->TryGetWebMessageAsString(&message);
+ if ( message == nullptr ) {
+ return S_OK;
+ }
+ const char *m = LPWSTRToCstr(message);
+
+ // check for internal messages
+ if (strcmp(m, "completed") == 0) {
+ completed(app);
+ return S_OK;
+ }
+ else if (strcmp(m, "initialised") == 0) {
+ loadAssets(app);
+ return S_OK;
+ }
+ else if (strcmp(m, "wails-drag") == 0) {
+ // We don't drag in fullscreen mode
+ if (!app->isFullscreen) {
+ ReleaseCapture();
+ SendMessage(this->window, WM_NCLBUTTONDOWN, HTCAPTION, 0);
+ }
+ return S_OK;
+ }
+ else {
+ messageFromWindowCallback(m);
+ }
+ delete[] m;
+ return S_OK;
+ }
+ HRESULT STDMETHODCALLTYPE
+ Invoke(ICoreWebView2 *sender,
+ ICoreWebView2PermissionRequestedEventArgs *args) {
+ printf("DDDDDDDDDDDD\n");
+
+ COREWEBVIEW2_PERMISSION_KIND kind;
+ args->get_PermissionKind(&kind);
+ if (kind == COREWEBVIEW2_PERMISSION_KIND_CLIPBOARD_READ) {
+ args->put_State(COREWEBVIEW2_PERMISSION_STATE_ALLOW);
+ }
+ return S_OK;
+ }
+
+};
+
+#endif
\ No newline at end of file
diff --git a/v2/internal/frontend/assetserver/assetserver_browser_dev.go b/v2/internal/frontend/assetserver/assetserver_browser_dev.go
new file mode 100644
index 000000000..dc1bfb15e
--- /dev/null
+++ b/v2/internal/frontend/assetserver/assetserver_browser_dev.go
@@ -0,0 +1,115 @@
+//go:build dev
+// +build dev
+
+package assetserver
+
+import (
+ "bytes"
+ "github.com/wailsapp/wails/v2/internal/frontend/runtime"
+ "github.com/wailsapp/wails/v2/pkg/options"
+ "golang.org/x/net/html"
+ "path/filepath"
+ "strings"
+)
+
+/*
+
+The assetserver for dev serves assets from disk.
+It injects a websocket based IPC script into `index.html`.
+
+*/
+
+import (
+ "os"
+)
+
+type BrowserAssetServer struct {
+ runtimeJS []byte
+ assetdir string
+ appOptions *options.App
+}
+
+func NewBrowserAssetServer(assetdir string, bindingsJSON string, appOptions *options.App) (*BrowserAssetServer, error) {
+ result := &BrowserAssetServer{
+ assetdir: assetdir,
+ appOptions: appOptions,
+ }
+
+ var buffer bytes.Buffer
+ buffer.WriteString(`window.wailsbindings='` + bindingsJSON + `';` + "\n")
+ buffer.Write(runtime.RuntimeDesktopJS)
+ result.runtimeJS = buffer.Bytes()
+ return result, nil
+}
+
+func (a *BrowserAssetServer) loadFileFromDisk(filename string) ([]byte, error) {
+ return os.ReadFile(filepath.Join(a.assetdir, filename))
+}
+
+func (a *BrowserAssetServer) processIndexHTML() ([]byte, error) {
+ indexHTML, err := a.loadFileFromDisk("index.html")
+ if err != nil {
+ return nil, err
+ }
+ htmlNode, err := getHTMLNode(indexHTML)
+ if err != nil {
+ return nil, err
+ }
+ err = appendSpinnerToBody(htmlNode)
+ if err != nil {
+ return nil, err
+ }
+ wailsOptions, err := extractOptions(indexHTML)
+ if err != nil {
+ return nil, err
+ }
+
+ if wailsOptions.disableIPCInjection == false {
+ err := insertScriptInHead(htmlNode, "/wails/ipc.js")
+ if err != nil {
+ return nil, err
+ }
+ }
+
+ if wailsOptions.disableRuntimeInjection == false {
+ err := insertScriptInHead(htmlNode, "/wails/runtime.js")
+ if err != nil {
+ return nil, err
+ }
+ }
+
+ var buffer bytes.Buffer
+ err = html.Render(&buffer, htmlNode)
+ if err != nil {
+ return nil, err
+ }
+ return buffer.Bytes(), nil
+}
+
+func (a *BrowserAssetServer) Load(filename string) ([]byte, string, error) {
+ var content []byte
+ var err error
+ switch filename {
+ case "/":
+ content, err = a.processIndexHTML()
+ case "/wails/runtime.js":
+ content = a.runtimeJS
+ case "/wails/ipc.js":
+ content = runtime.WebsocketIPC
+ default:
+ content, err = a.loadFileFromDisk(filename)
+ if strings.HasSuffix(filename, ".js") {
+ var buffer bytes.Buffer
+ buffer.WriteString("window.awaitIPC('" + filename + "', ()=>{")
+ buffer.Write(content)
+ buffer.WriteString(`
+});`)
+ content = buffer.Bytes()
+ }
+ }
+ if err != nil {
+ return nil, "", err
+ }
+ mimeType := GetMimetype(filename, content)
+ return content, mimeType, nil
+}
diff --git a/v2/internal/frontend/assetserver/assetserver_desktop.go b/v2/internal/frontend/assetserver/assetserver_desktop.go
new file mode 100644
index 000000000..1ec4a7532
--- /dev/null
+++ b/v2/internal/frontend/assetserver/assetserver_desktop.go
@@ -0,0 +1,156 @@
+package assetserver
+
+import (
+ "bytes"
+ "context"
+ "embed"
+ "fmt"
+ "github.com/leaanthony/debme"
+ "github.com/leaanthony/slicer"
+ "github.com/wailsapp/wails/v2/internal/frontend/runtime"
+ "github.com/wailsapp/wails/v2/internal/logger"
+ "io/fs"
+ "log"
+ "path/filepath"
+ "strings"
+)
+
+type DesktopAssetServer struct {
+ assets debme.Debme
+ runtimeJS []byte
+ assetdir string
+ logger *logger.Logger
+}
+
+func NewDesktopAssetServer(ctx context.Context, assets embed.FS, bindingsJSON string) (*DesktopAssetServer, error) {
+ result := &DesktopAssetServer{}
+
+ _logger := ctx.Value("logger")
+ if _logger != nil {
+ result.logger = _logger.(*logger.Logger)
+ }
+
+ _assetdir := ctx.Value("assetdir")
+ if _assetdir != nil {
+ result.assetdir = _assetdir.(string)
+ absdir, err := filepath.Abs(result.assetdir)
+ if err != nil {
+ return nil, err
+ }
+ result.LogDebug("Loading assets from: %s", absdir)
+ }
+
+ var buffer bytes.Buffer
+ buffer.WriteString(`window.wailsbindings='` + bindingsJSON + `';` + "\n")
+ buffer.Write(runtime.RuntimeDesktopJS)
+ result.runtimeJS = buffer.Bytes()
+ err := result.init(assets)
+ return result, err
+}
+
+func (d *DesktopAssetServer) LogDebug(message string, args ...interface{}) {
+ if d.logger != nil {
+ d.logger.Debug("[DesktopAssetServer] "+message, args...)
+ }
+}
+
+func (d *DesktopAssetServer) SetAssetDir(assetdir string) {
+ d.assetdir = assetdir
+}
+
+func PathToIndexHTML(assets embed.FS) (string, error) {
+ stat, err := fs.Stat(assets, "index.html")
+ if stat != nil {
+ return ".", nil
+ }
+ var indexFiles slicer.StringSlicer
+ err = fs.WalkDir(assets, ".", func(path string, d fs.DirEntry, err error) error {
+ if err != nil {
+ return err
+ }
+ if strings.HasSuffix(path, "index.html") {
+ indexFiles.Add(path)
+ }
+ return nil
+ })
+ if err != nil {
+ return "", err
+ }
+
+ if indexFiles.Length() > 1 {
+ return "", fmt.Errorf("multiple 'index.html' files found in assets")
+ }
+
+ path, _ := filepath.Split(indexFiles.AsSlice()[0])
+ return path, nil
+}
+
+func processAssets(assets embed.FS) (debme.Debme, error) {
+
+ result, err := debme.FS(assets, ".")
+ if err != nil {
+ return result, err
+ }
+ // Find index.html
+ path, err := PathToIndexHTML(assets)
+ if err != nil {
+ return debme.Debme{}, err
+ }
+ return debme.FS(assets, path)
+}
+
+func (a *DesktopAssetServer) init(assets embed.FS) error {
+
+ var err error
+ a.assets, err = processAssets(assets)
+ if err != nil {
+ return err
+ }
+ return nil
+}
+
+func (a *DesktopAssetServer) processIndexHTML() ([]byte, error) {
+ indexHTML, err := a.ReadFile("index.html")
+ if err != nil {
+ return nil, err
+ }
+ wailsOptions, err := extractOptions(indexHTML)
+ if err != nil {
+ log.Fatal(err)
+ return nil, err
+ }
+ if wailsOptions.disableRuntimeInjection == false {
+ indexHTML, err = injectHTML(string(indexHTML), ``)
+ if err != nil {
+ return nil, err
+ }
+ }
+ if wailsOptions.disableIPCInjection == false {
+ indexHTML, err = injectHTML(string(indexHTML), ``)
+ if err != nil {
+ return nil, err
+ }
+ }
+
+ return indexHTML, nil
+}
+
+func (a *DesktopAssetServer) Load(filename string) ([]byte, string, error) {
+ var content []byte
+ var err error
+ switch filename {
+ case "/":
+ content, err = a.processIndexHTML()
+ case "/wails/runtime.js":
+ content = a.runtimeJS
+ case "/wails/ipc.js":
+ content = runtime.DesktopIPC
+ default:
+ content, err = a.ReadFile(filename)
+ }
+ if err != nil {
+ return nil, "", err
+ }
+ mimeType := GetMimetype(filename, content)
+ return content, mimeType, nil
+}
diff --git a/v2/internal/frontend/assetserver/assetserver_desktop_dev.go b/v2/internal/frontend/assetserver/assetserver_desktop_dev.go
new file mode 100644
index 000000000..42726ae3a
--- /dev/null
+++ b/v2/internal/frontend/assetserver/assetserver_desktop_dev.go
@@ -0,0 +1,13 @@
+//go:build dev
+
+package assetserver
+
+import (
+ "os"
+ "path/filepath"
+)
+
+func (a *DesktopAssetServer) ReadFile(filename string) ([]byte, error) {
+ a.LogDebug("Loading file from disk: %s", filename)
+ return os.ReadFile(filepath.Join(a.assetdir, filename))
+}
diff --git a/v2/internal/frontend/assetserver/assetserver_desktop_production.go b/v2/internal/frontend/assetserver/assetserver_desktop_production.go
new file mode 100644
index 000000000..fb09ee1a3
--- /dev/null
+++ b/v2/internal/frontend/assetserver/assetserver_desktop_production.go
@@ -0,0 +1,7 @@
+//go:build production
+
+package assetserver
+
+func (a *DesktopAssetServer) ReadFile(filename string) ([]byte, error) {
+ return a.assets.ReadFile(filename)
+}
diff --git a/v2/internal/frontend/assetserver/common.go b/v2/internal/frontend/assetserver/common.go
new file mode 100644
index 000000000..0695d7f27
--- /dev/null
+++ b/v2/internal/frontend/assetserver/common.go
@@ -0,0 +1,163 @@
+package assetserver
+
+import (
+ "bytes"
+ "errors"
+ "fmt"
+ "golang.org/x/net/html"
+ "strings"
+)
+
+type optionType string
+
+const (
+ noAutoInject optionType = "noautoinject"
+ noAutoInjectRuntime optionType = "noautoinjectruntime"
+ noAutoInjectIPC optionType = "noautoinjectipc"
+)
+
+type Options struct {
+ disableRuntimeInjection bool
+ disableIPCInjection bool
+}
+
+func newOptions(optionString string) *Options {
+ var result = &Options{}
+ optionString = strings.ToLower(optionString)
+ options := strings.Split(optionString, ",")
+ for _, option := range options {
+ switch optionType(strings.TrimSpace(option)) {
+ case noAutoInject:
+ result.disableRuntimeInjection = true
+ result.disableIPCInjection = true
+ case noAutoInjectIPC:
+ result.disableIPCInjection = true
+ case noAutoInjectRuntime:
+ result.disableRuntimeInjection = true
+ }
+ }
+ return result
+}
+
+func injectHTML(input string, html string) ([]byte, error) {
+ splits := strings.Split(input, "")
+ if len(splits) != 2 {
+ return nil, fmt.Errorf("unable to locate a tag in your html")
+ }
+
+ var result bytes.Buffer
+ result.WriteString(splits[0])
+ result.WriteString(html)
+ result.WriteString("")
+ result.WriteString(splits[1])
+ return result.Bytes(), nil
+}
+
+func extractOptions(htmldata []byte) (*Options, error) {
+ doc, err := html.Parse(bytes.NewReader(htmldata))
+ if err != nil {
+ return nil, err
+ }
+ var extractor func(*html.Node) *Options
+ extractor = func(node *html.Node) *Options {
+ if node.Type == html.ElementNode && node.Data == "meta" {
+ isWailsOptionsTag := false
+ wailsOptions := ""
+ for _, attr := range node.Attr {
+ if isWailsOptionsTag && attr.Key == "content" {
+ wailsOptions = attr.Val
+ }
+ if attr.Val == "wails-options" {
+ isWailsOptionsTag = true
+ }
+ }
+ return newOptions(wailsOptions)
+ }
+ for child := node.FirstChild; child != nil; child = child.NextSibling {
+ result := extractor(child)
+ if result != nil {
+ return result
+ }
+ }
+ return nil
+ }
+ result := extractor(doc)
+ if result == nil {
+ result = &Options{}
+ }
+ return result, nil
+}
+
+func createScriptNode(scriptName string) *html.Node {
+ return &html.Node{
+ Type: html.ElementNode,
+ Data: "script",
+ Attr: []html.Attribute{
+ {
+ Key: "src",
+ Val: scriptName,
+ },
+ },
+ }
+}
+
+func createDivNode(id string) *html.Node {
+ return &html.Node{
+ Type: html.ElementNode,
+ Data: "div",
+ Attr: []html.Attribute{
+ {
+ Namespace: "",
+ Key: "id",
+ Val: id,
+ },
+ },
+ }
+}
+
+func insertScriptInHead(htmlNode *html.Node, scriptName string) error {
+ headNode := findFirstTag(htmlNode, "head")
+ if headNode == nil {
+ return errors.New("cannot find head in HTML")
+ }
+ scriptNode := createScriptNode(scriptName)
+ if headNode.FirstChild != nil {
+ headNode.InsertBefore(scriptNode, headNode.FirstChild)
+ } else {
+ headNode.AppendChild(scriptNode)
+ }
+ return nil
+}
+
+func appendSpinnerToBody(htmlNode *html.Node) error {
+ bodyNode := findFirstTag(htmlNode, "body")
+ if bodyNode == nil {
+ return errors.New("cannot find body in HTML")
+ }
+ scriptNode := createDivNode("wails-spinner")
+ bodyNode.AppendChild(scriptNode)
+ return nil
+}
+
+func getHTMLNode(htmldata []byte) (*html.Node, error) {
+ return html.Parse(bytes.NewReader(htmldata))
+}
+
+func findFirstTag(htmlnode *html.Node, tagName string) *html.Node {
+ var extractor func(*html.Node) *html.Node
+ var result *html.Node
+ extractor = func(node *html.Node) *html.Node {
+ if node.Type == html.ElementNode && node.Data == tagName {
+ return node
+ }
+ for child := node.FirstChild; child != nil; child = child.NextSibling {
+ result := extractor(child)
+ if result != nil {
+ return result
+ }
+ }
+ return nil
+ }
+ result = extractor(htmlnode)
+ return result
+}
diff --git a/v2/internal/frontend/assetserver/common_test.go b/v2/internal/frontend/assetserver/common_test.go
new file mode 100644
index 000000000..a60e1e12f
--- /dev/null
+++ b/v2/internal/frontend/assetserver/common_test.go
@@ -0,0 +1,70 @@
+package assetserver
+
+import (
+ "reflect"
+ "testing"
+)
+
+const realHTML = `
+
+
+ test3
+
+
+
+
+
+
+ Please enter your name below �
+
+
+ Greet
+
+
+
+
+
+
+`
+
+func genMeta(content string) []byte {
+ return []byte(" ")
+}
+
+func genOptions(runtime bool, bindings bool) *Options {
+ return &Options{
+ disableRuntimeInjection: runtime,
+ disableIPCInjection: bindings,
+ }
+}
+
+func Test_extractOptions(t *testing.T) {
+ tests := []struct {
+ name string
+ htmldata []byte
+ want *Options
+ wantError bool
+ }{
+ {"empty", []byte(""), &Options{}, false},
+ {"bad data", []byte("<"), &Options{}, false},
+ {"bad options", genMeta("noauto"), genOptions(false, false), false},
+ {"realhtml", []byte(realHTML), genOptions(true, true), false},
+ {"noautoinject", genMeta("noautoinject"), genOptions(true, true), false},
+ {"noautoinjectipc", genMeta("noautoinjectipc"), genOptions(false, true), false},
+ {"noautoinjectruntime", genMeta("noautoinjectruntime"), genOptions(true, false), false},
+ {"spaces", genMeta(" noautoinjectruntime "), genOptions(true, false), false},
+ {"multiple", genMeta("noautoinjectruntime,noautoinjectipc"), genOptions(true, true), false},
+ {"multiple spaces", genMeta(" noautoinjectruntime, noautoinjectipc "), genOptions(true, true), false},
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ got, err := extractOptions(tt.htmldata)
+ if !tt.wantError && err != nil {
+ t.Errorf("did not want error but got it")
+ }
+ if !reflect.DeepEqual(got, tt.want) {
+ t.Errorf("extractOptions() = %v, want %v", got, tt.want)
+ }
+ })
+ }
+}
diff --git a/v2/internal/frontend/assetserver/mimecache.go b/v2/internal/frontend/assetserver/mimecache.go
new file mode 100644
index 000000000..ae33f7a54
--- /dev/null
+++ b/v2/internal/frontend/assetserver/mimecache.go
@@ -0,0 +1,47 @@
+package assetserver
+
+import (
+ "net/http"
+ "path/filepath"
+ "strings"
+ "sync"
+
+ "github.com/gabriel-vasile/mimetype"
+)
+
+var (
+ cache = map[string]string{}
+ mutex sync.Mutex
+)
+
+func GetMimetype(filename string, data []byte) string {
+ mutex.Lock()
+ defer mutex.Unlock()
+
+ result := cache[filename]
+ if result != "" {
+ return result
+ }
+
+ detect := mimetype.Detect(data)
+ if detect == nil {
+ result = http.DetectContentType(data)
+ } else {
+ result = detect.String()
+ }
+
+ if filepath.Ext(filename) == ".css" && strings.HasPrefix(result, "text/plain") {
+ result = strings.Replace(result, "text/plain", "text/css", 1)
+ }
+
+ if filepath.Ext(filename) == ".js" && strings.HasPrefix(result, "text/plain") {
+ result = strings.Replace(result, "text/plain", "text/javascript", 1)
+ }
+
+ if result == "" {
+ result = "application/octet-stream"
+ }
+
+ cache[filename] = result
+ return result
+}
diff --git a/v2/internal/frontend/assetserver/mimecache_test.go b/v2/internal/frontend/assetserver/mimecache_test.go
new file mode 100644
index 000000000..d6dbb9dfc
--- /dev/null
+++ b/v2/internal/frontend/assetserver/mimecache_test.go
@@ -0,0 +1,26 @@
+package assetserver
+
+import "testing"
+
+func TestGetMimetype(t *testing.T) {
+ type args struct {
+ filename string
+ data []byte
+ }
+ tests := []struct {
+ name string
+ args args
+ want string
+ }{
+ // TODO: Add test cases.
+ {"css", args{"test.css", []byte("body{margin:0;padding:0;background-color:#d579b2}#app{font-family:Avenir,Helvetica,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;text-align:center;color:#2c3e50;background-color:#ededed}#nav{padding:30px}#nav a{font-weight:700;color:#2c\n3e50}#nav a.router-link-exact-active{color:#42b983}.hello[data-v-4e26ad49]{margin:10px 0}")}, "text/css; charset=utf-8"},
+ {"js", args{"test.js", []byte("let foo = 'bar'; console.log(foo);")}, "text/javascript; charset=utf-8"},
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ if got := GetMimetype(tt.args.filename, tt.args.data); got != tt.want {
+ t.Errorf("GetMimetype() = %v, want %v", got, tt.want)
+ }
+ })
+ }
+}
diff --git a/v2/internal/frontend/assetserver/testdata/index.html b/v2/internal/frontend/assetserver/testdata/index.html
new file mode 100644
index 000000000..76da518f4
--- /dev/null
+++ b/v2/internal/frontend/assetserver/testdata/index.html
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/v2/internal/frontend/assetserver/testdata/main.css b/v2/internal/frontend/assetserver/testdata/main.css
new file mode 100644
index 000000000..57b00e6c6
--- /dev/null
+++ b/v2/internal/frontend/assetserver/testdata/main.css
@@ -0,0 +1,39 @@
+
+html {
+ text-align: center;
+ color: white;
+ background-color: rgba(1, 1, 1, 0.1);
+}
+
+body {
+ color: white;
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif;
+ margin: 0;
+}
+
+#result {
+ margin-top: 1rem;
+}
+
+button {
+ -webkit-appearance: default-button;
+ padding: 6px;
+}
+
+#name {
+ border-radius: 3px;
+ outline: none;
+ height: 20px;
+ -webkit-font-smoothing: antialiased;
+}
+
+#logo {
+ width: 40%;
+ height: 40%;
+ padding-top: 20%;
+ margin: auto;
+ display: block;
+ background-position: center;
+ background-repeat: no-repeat;
+ background-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB2aWV3Qm94PSIwIDAgNTUxIDQzNiIgZmlsbC1ydWxlPSJldmVub2RkIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBzdHJva2UtbWl0ZXJsaW1pdD0iMiIgeG1sbnM6dj0iaHR0cHM6Ly92ZWN0YS5pby9uYW5vIj48ZyBmaWxsLXJ1bGU9Im5vbnplcm8iPjxwYXRoIGQ9Ik0xMDQuMDEgMzQ0LjM4OGgxOC40MDFsLTEuNzY4IDM5LjE2MSAxMi4xNDctMzkuMTYxaDE0Ljg2N2wtLjE4MSAzOS4xNjEgMTAuNTYxLTM5LjE2MWgxOC40MDFsLTIzLjI5NyA2Ni4xNzVoLTE2Ljk5N2wuMTgxLTQxLjM4My0xMi45MTcgNDEuMzgzaC0xNi45NTFsLTIuNDQ3LTY2LjE3NXptMTIwLjk3NSA0My4wNTloNy4zODhsLjIyNy0yNC41MjEtNy42MTUgMjQuNTIxem0tMjUuNzQ0IDIzLjExNmwyNC44ODMtNjYuMTc1aDIxLjgwMWw0LjY2NyA2Ni4xNzVoLTE4LjY3NGwuMDkyLTkuNzQ2aC0xMC45MjRsLTIuOTAxIDkuNzQ2aC0xOC45NDR6bTg4LjE4MyAwbDEwLjQ3LTY2LjE3NmgxOC40OTNsLTEwLjUxNiA2Ni4xNzUtMTguNDQ2LjAwMXptNjUuNzkzIDBsMTAuNTE2LTY2LjE3NWgxOC41MzZsLTcuODg2IDQ5Ljc2NmgxMy41NTJsLTIuNTgyIDE2LjQwOWgtMzIuMTM2em03NC43MjItMjAuMzUyYzIuMDU0IDEuNzIzIDQuMjE1IDMuMDUzIDYuNDgyIDMuOTlzNC40NCAxLjQwNCA2LjUyNiAxLjQwNGMxLjg0MyAwIDMuMzA4LS41MDYgNC4zOTYtMS41MThzMS42MzItMi4zOTUgMS42MzItNC4xNDhjMC0xLjUwOS0uNDU0LTMuMDEzLTEuMzU5LTQuNTA5cy0yLjY2LTMuNDgxLTUuMjU4LTUuOTU5Yy0zLjE0NC0zLjA1Mi01LjMwMy01Ljc0MS02LjQ4Mi04LjA2OXMtMS43NjYtNC44OTQtMS43NjYtNy43MDRjMC02LjMxNSAyLjAwMS0xMS4zMzIgNi4wMDUtMTUuMDQ4czkuNDM0LTUuNTc1IDE2LjI5NC01LjU3NWMyLjc4IDAgNS40MjIuMzEgNy45MzEuOTNzNS4wNiAxLjU3OSA3LjY2MSAyLjg3OGwtMi42MyAxNi4xMzZjLTEuOTk1LTEuMzktMy45MzUtMi40NDctNS44MjMtMy4xNzNzLTMuNjk0LTEuMDg5LTUuNDE3LTEuMDg5Yy0xLjU0MSAwLTIuNzU4LjQtMy42NDkgMS4ycy0xLjMzOCAxLjg5OC0xLjMzOCAzLjI4OGMwIDEuODc1IDEuNzA4IDQuNTAzIDUuMTIzIDcuODg2bC45OTcuOTk2YzMuNDQ1IDMuMzg2IDUuNzExIDYuMjg2IDYuNzk4IDguNzA1czEuNjMxIDUuMjA5IDEuNjMxIDguMzg0YzAgNy4wNzEtMi4xODMgMTIuNjQ2LTYuNTUgMTYuNzI0cy0xMC4zNDEgNi4xMi0xNy45MjUgNi4xMmMtMy4yMzQgMC02LjI5Mi0uMzg1LTkuMTc4LTEuMTU1cy01LjMxLTEuODM4LTcuMjc0LTMuMTk3bDMuMTczLTE3LjQ5NXoiIGZpbGw9IiNmZmYiLz48cGF0aCBkPSJNLjg4My0uMDgxTC4xMjEuMDgxLjI1Ni0uMDYzLjg4My0uMDgxeiIgZmlsbD0idXJsKCNBKSIgdHJhbnNmb3JtPSJtYXRyaXgoLTE2Ni41OTkgNC41NzEzMiA0LjU3MTMyIDE2Ni41OTkgMTQ3LjQwMyAxNjcuNjQ4KSIvPjxwYXRoIGQ9Ik0uODc4LS4yODVMLS4wNzMuNzEtMS4xODYuNTQyLjAxNS4yMDctLjg0Ni4wNzcuMzU1LS4yNThsLS44Ni0uMTNMLjY0OS0uNzFsLjIyOS40MjV6IiBmaWxsPSJ1cmwoI0IpIiB0cmFuc2Zvcm09Im1hdHJpeCgtMTA2LjQ0MyAtMTYuMDY2OSAtMTYuMDY2OSAxMDYuNDQzIDQyOC4xOSAxODguMDMzKSIvPjxwYXRoIGQ9Ik0uNDQtLjA0aDAgMEwuMjY1LS4wNTYuMTc3LjQzNy0uMzExLS4yNTUuMjYyLS40MzdoLjMwNkwuNDQtLjA0eiIgZmlsbD0idXJsKCNDKSIgdHJhbnNmb3JtPSJtYXRyaXgoLTExNC40ODQgLTE2Mi40MDggLTE2Mi40MDggMTE0LjQ4NCAzMzMuMjkxIDI4NS44MDQpIi8+PHBhdGggZD0iTS41IDBoMCAwIDB6IiBmaWxsPSJ1cmwoI0QpIiB0cmFuc2Zvcm09Im1hdHJpeCg2MS42OTE5IDU4LjgwOTEgNTguODA5MSAtNjEuNjkxOSAyNTguNjMxIDE4MC40MTMpIi8+PHBhdGggZD0iTS42MjItLjExNWguMTM5bC4wNDUuMTAyLjAyLjE5NS0uMjA0LS4yOTd6IiBmaWxsPSJ1cmwoI0UpIiB0cmFuc2Zvcm09Im1hdHJpeCgyMzguMTI2IDI5OC44OTMgMjk4Ljg5MyAtMjM4LjEyNiAxMTMuNTE2IC0xNTAuNTM2KSIvPjxwYXRoIGQ9Ik0uNDY3LjAwNUwuNDkuMDYyLjI3MS0uMDYyLjQ2Ny4wMDV6IiBmaWxsPSJ1cmwoI0YpIiB0cmFuc2Zvcm09Im1hdHJpeCgtMzY5LjUyOSAtOTcuNDExOCAtOTcuNDExOCAzNjkuNTI5IDU4Mi4zOCA5NC4wMjcpIi8+PGcgZmlsbD0idXJsKCNCKSI+PHBhdGggZD0iTS4yLjAwMWwuMDE5LS4wMTkuMzk1LjAzLS4wOTUuMDc3TC4yODIuMDY4LjIuMTM1LjQ2My4xOTQuMzc0LjI2Ni4xMzguMTg2aDAgMEwuMDQ3LjAzMy0uMTMxLS4yNjYuMi4wMDF6IiB0cmFuc2Zvcm09Im1hdHJpeCgtNDk2LjE1NiAtNTMuOTc1MSAtNTMuOTc1MSA0OTYuMTU2IDM2Ny44ODggMTI1LjA4NSkiLz48cGF0aCBkPSJNLjczNSAwaDAgMCAweiIgdHJhbnNmb3JtPSJtYXRyaXgoMTg1LjA3NiAxNzYuNDI3IDE3Ni40MjcgLTE4NS4wNzYgMTUzLjQ0NiA4MC4xNDg4KSIvPjwvZz48L2c+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJBIiB4MT0iMCIgeTE9IjAiIHgyPSIxIiB5Mj0iMCIgZ3JhZGllbnRUcmFuc2Zvcm09Im1hdHJpeCgxLC0zLjQ2OTQ1ZS0xOCwtMy40Njk0NWUtMTgsLTEsMCwtMy4wNTc2MWUtMDYpIiB4bGluazpocmVmPSIjRyI+PHN0b3Agb2Zmc2V0PSIwIiBzdG9wLWNvbG9yPSIjZTMzMjMyIi8+PHN0b3Agb2Zmc2V0PSIxIiBzdG9wLWNvbG9yPSIjNmIwMDBkIi8+PC9saW5lYXJHcmFkaWVudD48bGluZWFyR3JhZGllbnQgaWQ9IkIiIHgxPSIwIiB5MT0iMCIgeDI9IjEiIHkyPSIwIiB4bGluazpocmVmPSIjRyI+PHN0b3Agb2Zmc2V0PSIwIiBzdG9wLWNvbG9yPSIjZTMzMjMyIi8+PHN0b3Agb2Zmc2V0PSIxIiBzdG9wLWNvbG9yPSIjNmIwMDBkIi8+PC9saW5lYXJHcmFkaWVudD48bGluZWFyR3JhZGllbnQgaWQ9IkMiIHgxPSIwIiB5MT0iMCIgeDI9IjEiIHkyPSIwIiBncmFkaWVudFRyYW5zZm9ybT0ibWF0cml4KDEsLTEuMTEwMjJlLTE2LC0xLjExMDIyZS0xNiwtMSwwLC0yLjYxODYxZS0wNikiIHhsaW5rOmhyZWY9IiNHIj48c3RvcCBvZmZzZXQ9IjAiIHN0b3AtY29sb3I9IiNlMzMyMzIiLz48c3RvcCBvZmZzZXQ9IjEiIHN0b3AtY29sb3I9IiM2YjAwMGQiLz48L2xpbmVhckdyYWRpZW50PjxsaW5lYXJHcmFkaWVudCBpZD0iRCIgeDE9IjAiIHkxPSIwIiB4Mj0iMSIgeTI9IjAiIGdyYWRpZW50VHJhbnNmb3JtPSJtYXRyaXgoMSwtNS41NTExMmUtMTcsLTUuNTUxMTJlLTE3LC0xLDAsLTEuNTc1NjJlLTA2KSIgeGxpbms6aHJlZj0iI0ciPjxzdG9wIG9mZnNldD0iMCIgc3RvcC1jb2xvcj0iI2UzMzIzMiIvPjxzdG9wIG9mZnNldD0iMSIgc3RvcC1jb2xvcj0iIzZiMDAwZCIvPjwvbGluZWFyR3JhZGllbnQ+PGxpbmVhckdyYWRpZW50IGlkPSJFIiB4MT0iMCIgeTE9IjAiIHgyPSIxIiB5Mj0iMCIgZ3JhZGllbnRUcmFuc2Zvcm09Im1hdHJpeCgtMC44MDE4OTksLTAuNTk3NDYsLTAuNTk3NDYsMC44MDE4OTksMS4zNDk1LDAuNDQ3NDU3KSIgeGxpbms6aHJlZj0iI0ciPjxzdG9wIG9mZnNldD0iMCIgc3RvcC1jb2xvcj0iI2UzMzIzMiIvPjxzdG9wIG9mZnNldD0iMSIgc3RvcC1jb2xvcj0iIzZiMDAwZCIvPjwvbGluZWFyR3JhZGllbnQ+PGxpbmVhckdyYWRpZW50IGlkPSJGIiB4MT0iMCIgeTE9IjAiIHgyPSIxIiB5Mj0iMCIgZ3JhZGllbnRUcmFuc2Zvcm09Im1hdHJpeCgxLC0yLjc3NTU2ZS0xNywtMi43NzU1NmUtMTcsLTEsMCwtMS45MjgyNmUtMDYpIiB4bGluazpocmVmPSIjRyI+PHN0b3Agb2Zmc2V0PSIwIiBzdG9wLWNvbG9yPSIjZTMzMjMyIi8+PHN0b3Agb2Zmc2V0PSIxIiBzdG9wLWNvbG9yPSIjNmIwMDBkIi8+PC9saW5lYXJHcmFkaWVudD48bGluZWFyR3JhZGllbnQgaWQ9IkciIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIi8+PC9kZWZzPjwvc3ZnPg==");
+}
diff --git a/v2/internal/frontend/assetserver/testdata/main.js b/v2/internal/frontend/assetserver/testdata/main.js
new file mode 100644
index 000000000..274b4667c
--- /dev/null
+++ b/v2/internal/frontend/assetserver/testdata/main.js
@@ -0,0 +1,20 @@
+import {ready} from '@wails/runtime';
+
+ready(() => {
+ // Get input + focus
+ let nameElement = document.getElementById("name");
+ nameElement.focus();
+
+ // Setup the greet function
+ window.greet = function () {
+
+ // Get name
+ let name = nameElement.value;
+
+ // Call App.Greet(name)
+ window.backend.main.App.Greet(name).then((result) => {
+ // Update result with data back from App.Greet()
+ document.getElementById("result").innerText = result;
+ });
+ };
+});
\ No newline at end of file
diff --git a/v2/internal/frontend/assetserver/testdata/subdir/index.html b/v2/internal/frontend/assetserver/testdata/subdir/index.html
new file mode 100644
index 000000000..76da518f4
--- /dev/null
+++ b/v2/internal/frontend/assetserver/testdata/subdir/index.html
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/v2/internal/frontend/assetserver/testdata/subdir/main.css b/v2/internal/frontend/assetserver/testdata/subdir/main.css
new file mode 100644
index 000000000..57b00e6c6
--- /dev/null
+++ b/v2/internal/frontend/assetserver/testdata/subdir/main.css
@@ -0,0 +1,39 @@
+
+html {
+ text-align: center;
+ color: white;
+ background-color: rgba(1, 1, 1, 0.1);
+}
+
+body {
+ color: white;
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif;
+ margin: 0;
+}
+
+#result {
+ margin-top: 1rem;
+}
+
+button {
+ -webkit-appearance: default-button;
+ padding: 6px;
+}
+
+#name {
+ border-radius: 3px;
+ outline: none;
+ height: 20px;
+ -webkit-font-smoothing: antialiased;
+}
+
+#logo {
+ width: 40%;
+ height: 40%;
+ padding-top: 20%;
+ margin: auto;
+ display: block;
+ background-position: center;
+ background-repeat: no-repeat;
+ background-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB2aWV3Qm94PSIwIDAgNTUxIDQzNiIgZmlsbC1ydWxlPSJldmVub2RkIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBzdHJva2UtbWl0ZXJsaW1pdD0iMiIgeG1sbnM6dj0iaHR0cHM6Ly92ZWN0YS5pby9uYW5vIj48ZyBmaWxsLXJ1bGU9Im5vbnplcm8iPjxwYXRoIGQ9Ik0xMDQuMDEgMzQ0LjM4OGgxOC40MDFsLTEuNzY4IDM5LjE2MSAxMi4xNDctMzkuMTYxaDE0Ljg2N2wtLjE4MSAzOS4xNjEgMTAuNTYxLTM5LjE2MWgxOC40MDFsLTIzLjI5NyA2Ni4xNzVoLTE2Ljk5N2wuMTgxLTQxLjM4My0xMi45MTcgNDEuMzgzaC0xNi45NTFsLTIuNDQ3LTY2LjE3NXptMTIwLjk3NSA0My4wNTloNy4zODhsLjIyNy0yNC41MjEtNy42MTUgMjQuNTIxem0tMjUuNzQ0IDIzLjExNmwyNC44ODMtNjYuMTc1aDIxLjgwMWw0LjY2NyA2Ni4xNzVoLTE4LjY3NGwuMDkyLTkuNzQ2aC0xMC45MjRsLTIuOTAxIDkuNzQ2aC0xOC45NDR6bTg4LjE4MyAwbDEwLjQ3LTY2LjE3NmgxOC40OTNsLTEwLjUxNiA2Ni4xNzUtMTguNDQ2LjAwMXptNjUuNzkzIDBsMTAuNTE2LTY2LjE3NWgxOC41MzZsLTcuODg2IDQ5Ljc2NmgxMy41NTJsLTIuNTgyIDE2LjQwOWgtMzIuMTM2em03NC43MjItMjAuMzUyYzIuMDU0IDEuNzIzIDQuMjE1IDMuMDUzIDYuNDgyIDMuOTlzNC40NCAxLjQwNCA2LjUyNiAxLjQwNGMxLjg0MyAwIDMuMzA4LS41MDYgNC4zOTYtMS41MThzMS42MzItMi4zOTUgMS42MzItNC4xNDhjMC0xLjUwOS0uNDU0LTMuMDEzLTEuMzU5LTQuNTA5cy0yLjY2LTMuNDgxLTUuMjU4LTUuOTU5Yy0zLjE0NC0zLjA1Mi01LjMwMy01Ljc0MS02LjQ4Mi04LjA2OXMtMS43NjYtNC44OTQtMS43NjYtNy43MDRjMC02LjMxNSAyLjAwMS0xMS4zMzIgNi4wMDUtMTUuMDQ4czkuNDM0LTUuNTc1IDE2LjI5NC01LjU3NWMyLjc4IDAgNS40MjIuMzEgNy45MzEuOTNzNS4wNiAxLjU3OSA3LjY2MSAyLjg3OGwtMi42MyAxNi4xMzZjLTEuOTk1LTEuMzktMy45MzUtMi40NDctNS44MjMtMy4xNzNzLTMuNjk0LTEuMDg5LTUuNDE3LTEuMDg5Yy0xLjU0MSAwLTIuNzU4LjQtMy42NDkgMS4ycy0xLjMzOCAxLjg5OC0xLjMzOCAzLjI4OGMwIDEuODc1IDEuNzA4IDQuNTAzIDUuMTIzIDcuODg2bC45OTcuOTk2YzMuNDQ1IDMuMzg2IDUuNzExIDYuMjg2IDYuNzk4IDguNzA1czEuNjMxIDUuMjA5IDEuNjMxIDguMzg0YzAgNy4wNzEtMi4xODMgMTIuNjQ2LTYuNTUgMTYuNzI0cy0xMC4zNDEgNi4xMi0xNy45MjUgNi4xMmMtMy4yMzQgMC02LjI5Mi0uMzg1LTkuMTc4LTEuMTU1cy01LjMxLTEuODM4LTcuMjc0LTMuMTk3bDMuMTczLTE3LjQ5NXoiIGZpbGw9IiNmZmYiLz48cGF0aCBkPSJNLjg4My0uMDgxTC4xMjEuMDgxLjI1Ni0uMDYzLjg4My0uMDgxeiIgZmlsbD0idXJsKCNBKSIgdHJhbnNmb3JtPSJtYXRyaXgoLTE2Ni41OTkgNC41NzEzMiA0LjU3MTMyIDE2Ni41OTkgMTQ3LjQwMyAxNjcuNjQ4KSIvPjxwYXRoIGQ9Ik0uODc4LS4yODVMLS4wNzMuNzEtMS4xODYuNTQyLjAxNS4yMDctLjg0Ni4wNzcuMzU1LS4yNThsLS44Ni0uMTNMLjY0OS0uNzFsLjIyOS40MjV6IiBmaWxsPSJ1cmwoI0IpIiB0cmFuc2Zvcm09Im1hdHJpeCgtMTA2LjQ0MyAtMTYuMDY2OSAtMTYuMDY2OSAxMDYuNDQzIDQyOC4xOSAxODguMDMzKSIvPjxwYXRoIGQ9Ik0uNDQtLjA0aDAgMEwuMjY1LS4wNTYuMTc3LjQzNy0uMzExLS4yNTUuMjYyLS40MzdoLjMwNkwuNDQtLjA0eiIgZmlsbD0idXJsKCNDKSIgdHJhbnNmb3JtPSJtYXRyaXgoLTExNC40ODQgLTE2Mi40MDggLTE2Mi40MDggMTE0LjQ4NCAzMzMuMjkxIDI4NS44MDQpIi8+PHBhdGggZD0iTS41IDBoMCAwIDB6IiBmaWxsPSJ1cmwoI0QpIiB0cmFuc2Zvcm09Im1hdHJpeCg2MS42OTE5IDU4LjgwOTEgNTguODA5MSAtNjEuNjkxOSAyNTguNjMxIDE4MC40MTMpIi8+PHBhdGggZD0iTS42MjItLjExNWguMTM5bC4wNDUuMTAyLjAyLjE5NS0uMjA0LS4yOTd6IiBmaWxsPSJ1cmwoI0UpIiB0cmFuc2Zvcm09Im1hdHJpeCgyMzguMTI2IDI5OC44OTMgMjk4Ljg5MyAtMjM4LjEyNiAxMTMuNTE2IC0xNTAuNTM2KSIvPjxwYXRoIGQ9Ik0uNDY3LjAwNUwuNDkuMDYyLjI3MS0uMDYyLjQ2Ny4wMDV6IiBmaWxsPSJ1cmwoI0YpIiB0cmFuc2Zvcm09Im1hdHJpeCgtMzY5LjUyOSAtOTcuNDExOCAtOTcuNDExOCAzNjkuNTI5IDU4Mi4zOCA5NC4wMjcpIi8+PGcgZmlsbD0idXJsKCNCKSI+PHBhdGggZD0iTS4yLjAwMWwuMDE5LS4wMTkuMzk1LjAzLS4wOTUuMDc3TC4yODIuMDY4LjIuMTM1LjQ2My4xOTQuMzc0LjI2Ni4xMzguMTg2aDAgMEwuMDQ3LjAzMy0uMTMxLS4yNjYuMi4wMDF6IiB0cmFuc2Zvcm09Im1hdHJpeCgtNDk2LjE1NiAtNTMuOTc1MSAtNTMuOTc1MSA0OTYuMTU2IDM2Ny44ODggMTI1LjA4NSkiLz48cGF0aCBkPSJNLjczNSAwaDAgMCAweiIgdHJhbnNmb3JtPSJtYXRyaXgoMTg1LjA3NiAxNzYuNDI3IDE3Ni40MjcgLTE4NS4wNzYgMTUzLjQ0NiA4MC4xNDg4KSIvPjwvZz48L2c+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJBIiB4MT0iMCIgeTE9IjAiIHgyPSIxIiB5Mj0iMCIgZ3JhZGllbnRUcmFuc2Zvcm09Im1hdHJpeCgxLC0zLjQ2OTQ1ZS0xOCwtMy40Njk0NWUtMTgsLTEsMCwtMy4wNTc2MWUtMDYpIiB4bGluazpocmVmPSIjRyI+PHN0b3Agb2Zmc2V0PSIwIiBzdG9wLWNvbG9yPSIjZTMzMjMyIi8+PHN0b3Agb2Zmc2V0PSIxIiBzdG9wLWNvbG9yPSIjNmIwMDBkIi8+PC9saW5lYXJHcmFkaWVudD48bGluZWFyR3JhZGllbnQgaWQ9IkIiIHgxPSIwIiB5MT0iMCIgeDI9IjEiIHkyPSIwIiB4bGluazpocmVmPSIjRyI+PHN0b3Agb2Zmc2V0PSIwIiBzdG9wLWNvbG9yPSIjZTMzMjMyIi8+PHN0b3Agb2Zmc2V0PSIxIiBzdG9wLWNvbG9yPSIjNmIwMDBkIi8+PC9saW5lYXJHcmFkaWVudD48bGluZWFyR3JhZGllbnQgaWQ9IkMiIHgxPSIwIiB5MT0iMCIgeDI9IjEiIHkyPSIwIiBncmFkaWVudFRyYW5zZm9ybT0ibWF0cml4KDEsLTEuMTEwMjJlLTE2LC0xLjExMDIyZS0xNiwtMSwwLC0yLjYxODYxZS0wNikiIHhsaW5rOmhyZWY9IiNHIj48c3RvcCBvZmZzZXQ9IjAiIHN0b3AtY29sb3I9IiNlMzMyMzIiLz48c3RvcCBvZmZzZXQ9IjEiIHN0b3AtY29sb3I9IiM2YjAwMGQiLz48L2xpbmVhckdyYWRpZW50PjxsaW5lYXJHcmFkaWVudCBpZD0iRCIgeDE9IjAiIHkxPSIwIiB4Mj0iMSIgeTI9IjAiIGdyYWRpZW50VHJhbnNmb3JtPSJtYXRyaXgoMSwtNS41NTExMmUtMTcsLTUuNTUxMTJlLTE3LC0xLDAsLTEuNTc1NjJlLTA2KSIgeGxpbms6aHJlZj0iI0ciPjxzdG9wIG9mZnNldD0iMCIgc3RvcC1jb2xvcj0iI2UzMzIzMiIvPjxzdG9wIG9mZnNldD0iMSIgc3RvcC1jb2xvcj0iIzZiMDAwZCIvPjwvbGluZWFyR3JhZGllbnQ+PGxpbmVhckdyYWRpZW50IGlkPSJFIiB4MT0iMCIgeTE9IjAiIHgyPSIxIiB5Mj0iMCIgZ3JhZGllbnRUcmFuc2Zvcm09Im1hdHJpeCgtMC44MDE4OTksLTAuNTk3NDYsLTAuNTk3NDYsMC44MDE4OTksMS4zNDk1LDAuNDQ3NDU3KSIgeGxpbms6aHJlZj0iI0ciPjxzdG9wIG9mZnNldD0iMCIgc3RvcC1jb2xvcj0iI2UzMzIzMiIvPjxzdG9wIG9mZnNldD0iMSIgc3RvcC1jb2xvcj0iIzZiMDAwZCIvPjwvbGluZWFyR3JhZGllbnQ+PGxpbmVhckdyYWRpZW50IGlkPSJGIiB4MT0iMCIgeTE9IjAiIHgyPSIxIiB5Mj0iMCIgZ3JhZGllbnRUcmFuc2Zvcm09Im1hdHJpeCgxLC0yLjc3NTU2ZS0xNywtMi43NzU1NmUtMTcsLTEsMCwtMS45MjgyNmUtMDYpIiB4bGluazpocmVmPSIjRyI+PHN0b3Agb2Zmc2V0PSIwIiBzdG9wLWNvbG9yPSIjZTMzMjMyIi8+PHN0b3Agb2Zmc2V0PSIxIiBzdG9wLWNvbG9yPSIjNmIwMDBkIi8+PC9saW5lYXJHcmFkaWVudD48bGluZWFyR3JhZGllbnQgaWQ9IkciIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIi8+PC9kZWZzPjwvc3ZnPg==");
+}
diff --git a/v2/internal/frontend/assetserver/testdata/subdir/main.js b/v2/internal/frontend/assetserver/testdata/subdir/main.js
new file mode 100644
index 000000000..274b4667c
--- /dev/null
+++ b/v2/internal/frontend/assetserver/testdata/subdir/main.js
@@ -0,0 +1,20 @@
+import {ready} from '@wails/runtime';
+
+ready(() => {
+ // Get input + focus
+ let nameElement = document.getElementById("name");
+ nameElement.focus();
+
+ // Setup the greet function
+ window.greet = function () {
+
+ // Get name
+ let name = nameElement.value;
+
+ // Call App.Greet(name)
+ window.backend.main.App.Greet(name).then((result) => {
+ // Update result with data back from App.Greet()
+ document.getElementById("result").innerText = result;
+ });
+ };
+});
\ No newline at end of file
diff --git a/v2/internal/frontend/assetserver/testdata/testdata.go b/v2/internal/frontend/assetserver/testdata/testdata.go
new file mode 100644
index 000000000..5387070ec
--- /dev/null
+++ b/v2/internal/frontend/assetserver/testdata/testdata.go
@@ -0,0 +1,6 @@
+package testdata
+
+import "embed"
+
+//go:embed index.html main.css main.js
+var TopLevelFS embed.FS
diff --git a/v2/internal/frontend/calls.go b/v2/internal/frontend/calls.go
new file mode 100644
index 000000000..3983c24bf
--- /dev/null
+++ b/v2/internal/frontend/calls.go
@@ -0,0 +1,5 @@
+package frontend
+
+type Calls interface {
+ Callback(string)
+}
diff --git a/v2/internal/frontend/desktop/darwin/AppDelegate.h b/v2/internal/frontend/desktop/darwin/AppDelegate.h
new file mode 100644
index 000000000..3799aae04
--- /dev/null
+++ b/v2/internal/frontend/desktop/darwin/AppDelegate.h
@@ -0,0 +1,20 @@
+//
+// AppDelegate.h
+// test
+//
+// Created by Lea Anthony on 10/10/21.
+//
+
+#ifndef AppDelegate_h
+#define AppDelegate_h
+
+#import
+
+@interface AppDelegate : NSResponder
+
+@property bool alwaysOnTop;
+@property (retain) NSWindow* mainWindow;
+
+@end
+
+#endif /* AppDelegate_h */
diff --git a/v2/internal/frontend/desktop/darwin/AppDelegate.m b/v2/internal/frontend/desktop/darwin/AppDelegate.m
new file mode 100644
index 000000000..24cfaa017
--- /dev/null
+++ b/v2/internal/frontend/desktop/darwin/AppDelegate.m
@@ -0,0 +1,53 @@
+//
+// AppDelegate.m
+// test
+//
+// Created by Lea Anthony on 10/10/21.
+//
+
+#import
+#import
+
+#import "AppDelegate.h"
+
+@implementation AppDelegate
+- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender {
+ return NO;
+}
+- (void)applicationWillFinishLaunching:(NSNotification *)aNotification {
+ [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
+ [self.mainWindow makeKeyAndOrderFront:self];
+ if (self.alwaysOnTop) {
+ [self.mainWindow setLevel:NSStatusWindowLevel];
+ }
+}
+
+- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
+ [NSApp activateIgnoringOtherApps:YES];
+}
+//
+//- (void) CreateMenu {
+// [NSApplication sharedApplication];
+// menubar = [[NSMenu new] autorelease];
+// id appMenuItem = [[NSMenuItem new] autorelease];
+// [menubar addItem:appMenuItem];
+// [NSApp setMainMenu:menubar];
+// id appMenu = [[NSMenu new] autorelease];
+// id appName = [[NSProcessInfo processInfo] processName];
+// id quitTitle = [@"Quit " stringByAppendingString:appName];
+// id quitMenuItem = [[[NSMenuItem alloc] initWithTitle:quitTitle
+// action:@selector(terminate:) keyEquivalent:@"q"]
+// autorelease];
+// [appMenu addItem:quitMenuItem];
+// [appMenuItem setSubmenu:appMenu];
+//}
+//
+//- (void) dealloc {
+// [super dealloc];
+// window = nil;
+// menubar = nil;
+//}
+
+@synthesize touchBar;
+
+@end
diff --git a/v2/internal/frontend/desktop/darwin/Application.h b/v2/internal/frontend/desktop/darwin/Application.h
new file mode 100644
index 000000000..05ead41a6
--- /dev/null
+++ b/v2/internal/frontend/desktop/darwin/Application.h
@@ -0,0 +1,44 @@
+//
+// Application.h
+// test
+//
+// Created by Lea Anthony on 10/10/21.
+//
+
+#ifndef Application_h
+#define Application_h
+
+#import
+#import
+#import "WailsContext.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);
+void Run(void*);
+
+void SetTitle(void* ctx, const char *title);
+void Center(void* ctx);
+void SetSize(void* ctx, int width, int height);
+void SetMinSize(void* ctx, int width, int height);
+void SetMaxSize(void* ctx, int width, int height);
+void SetPosition(void* ctx, int x, int y);
+void Fullscreen(void* ctx);
+void UnFullscreen(void* ctx);
+void Minimise(void* ctx);
+void UnMinimise(void* ctx);
+void Maximise(void* ctx);
+void UnMaximise(void* ctx);
+void Hide(void* ctx);
+void Show(void* ctx);
+void SetRGBA(void* ctx, int r, int g, int b, int a);
+void ExecJS(void* ctx, const char*);
+void Quit(void*);
+
+const char* GetSize(void *ctx);
+const char* GetPos(void *ctx);
+
+void ProcessURLResponse(void *inctx, const char *url, const char *contentType, const char *data, int datalength);
+
+void MessageDialog(void *inctx, const char* dialogType, const char* title, const char* message, const char* button1, const char* button2, const char* button3, const char* button4, const char* defaultButton, const char* cancelButton);
+void OpenFileDialog(void *inctx, const char* title, const char* defaultFilename, const char* defaultDirectory, int allowDirectories, int allowFiles, int canCreateDirectories, int treatPackagesAsDirectories, int resolveAliases, int showHiddenFiles, int allowMultipleSelection, const char* filters);
+void SaveFileDialog(void *inctx, const char* title, const char* defaultFilename, const char* defaultDirectory, int canCreateDirectories, int treatPackagesAsDirectories, int showHiddenFiles, const char* filters);
+#endif /* Application_h */
diff --git a/v2/internal/frontend/desktop/darwin/Application.m b/v2/internal/frontend/desktop/darwin/Application.m
new file mode 100644
index 000000000..ac730d523
--- /dev/null
+++ b/v2/internal/frontend/desktop/darwin/Application.m
@@ -0,0 +1,214 @@
+//
+// Application.m
+//
+// Created by Lea Anthony on 10/10/21.
+//
+
+#import
+#import
+#import "WailsContext.h"
+#import "Application.h"
+#import "AppDelegate.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) {
+
+ WailsContext *result = [WailsContext new];
+
+ result.debug = debug;
+
+ [result CreateWindow:width :height :frameless :resizable :fullscreen :fullSizeContent :hideTitleBar :titlebarAppearsTransparent :hideTitle :useToolbar :hideToolbarSeparator :webviewIsTransparent :hideWindowOnClose :appearance :windowIsTranslucent];
+ [result SetTitle:title];
+ [result Center];
+
+ result.alwaysOnTop = alwaysOnTop;
+ result.hideOnClose = hideWindowOnClose;
+
+ return result;
+}
+
+void ProcessURLResponse(void *inctx, const char *url, const char *contentType, const char* data, int datalength) {
+ WailsContext *ctx = (__bridge WailsContext*) inctx;
+ NSString *nsurl = [[NSString alloc] initWithUTF8String:url];
+ NSString *nsContentType = [[NSString alloc] initWithUTF8String:contentType];
+ NSData *nsdata = [NSData dataWithBytes:data length:datalength];
+
+ [ctx processURLResponse:nsurl :nsContentType :nsdata];
+}
+
+void ExecJS(void* inctx, const char *script) {
+ WailsContext *ctx = (__bridge WailsContext*) inctx;
+ ON_MAIN_THREAD(
+ [ctx ExecJS:script];
+ );
+}
+
+void SetTitle(void* inctx, const char *title) {
+ WailsContext *ctx = (__bridge WailsContext*) inctx;
+ ON_MAIN_THREAD(
+ [ctx SetTitle:title];
+ );
+}
+
+
+void SetRGBA(void *inctx, int r, int g, int b, int a) {
+ WailsContext *ctx = (__bridge WailsContext*) inctx;
+ ON_MAIN_THREAD(
+ [ctx SetRGBA:r :g :b :a];
+ );
+}
+
+void SetSize(void* inctx, int width, int height) {
+ WailsContext *ctx = (__bridge WailsContext*) inctx;
+ ON_MAIN_THREAD(
+ [ctx SetSize:width :height];
+ );
+}
+
+void SetMinSize(void* inctx, int width, int height) {
+ WailsContext *ctx = (__bridge WailsContext*) inctx;
+ ON_MAIN_THREAD(
+ [ctx SetMinSize:width :height];
+ );
+}
+
+void SetMaxSize(void* inctx, int width, int height) {
+ WailsContext *ctx = (__bridge WailsContext*) inctx;
+ ON_MAIN_THREAD(
+ [ctx SetMaxSize:width :height];
+ );
+}
+
+void SetPosition(void* inctx, int x, int y) {
+ WailsContext *ctx = (__bridge WailsContext*) inctx;
+ ON_MAIN_THREAD(
+ [ctx SetSize:x :y];
+ );
+}
+
+void Center(void* inctx) {
+ WailsContext *ctx = (__bridge WailsContext*) inctx;
+ ON_MAIN_THREAD(
+ [ctx Center];
+ );
+}
+
+void Fullscreen(void* inctx) {
+ WailsContext *ctx = (__bridge WailsContext*) inctx;
+ ON_MAIN_THREAD(
+ [ctx Fullscreen];
+ );
+}
+
+void UnFullscreen(void* inctx) {
+ WailsContext *ctx = (__bridge WailsContext*) inctx;
+ ON_MAIN_THREAD(
+ [ctx UnFullscreen];
+ );
+}
+
+void Minimise(void* inctx) {
+ WailsContext *ctx = (__bridge WailsContext*) inctx;
+ ON_MAIN_THREAD(
+ [ctx Minimise];
+ );
+}
+
+void UnMinimise(void* inctx) {
+ WailsContext *ctx = (__bridge WailsContext*) inctx;
+ ON_MAIN_THREAD(
+ [ctx UnMinimise];
+ );
+}
+
+void Maximise(void* inctx) {
+ WailsContext *ctx = (__bridge WailsContext*) inctx;
+ ON_MAIN_THREAD(
+ [ctx Maximise];
+ );
+}
+
+const char* GetSize(void *inctx) {
+ WailsContext *ctx = (__bridge WailsContext*) inctx;
+ NSRect frame = [ctx.mainWindow frame];
+ NSString *result = [NSString stringWithFormat:@"%d,%d", (int)frame.size.width, (int)frame.size.height];
+ return [result UTF8String];
+}
+
+const char* GetPos(void *inctx) {
+ WailsContext *ctx = (__bridge WailsContext*) inctx;
+ NSScreen* screen = [ctx getCurrentScreen];
+ NSRect windowFrame = [ctx.mainWindow frame];
+ NSRect screenFrame = [screen visibleFrame];
+ int x = windowFrame.origin.x - screenFrame.origin.x;
+ int y = windowFrame.origin.y - screenFrame.origin.y;
+ y = screenFrame.size.height - y - windowFrame.size.height;
+ NSString *result = [NSString stringWithFormat:@"%d,%d",x,y];
+ return [result UTF8String];
+
+}
+
+void UnMaximise(void* inctx) {
+ WailsContext *ctx = (__bridge WailsContext*) inctx;
+ ON_MAIN_THREAD(
+ [ctx UnMaximise];
+ );
+}
+
+void Quit(void *inctx) {
+ WailsContext *ctx = (__bridge WailsContext*) inctx;
+ [NSApp stop:ctx];
+}
+
+void Hide(void *inctx) {
+ WailsContext *ctx = (__bridge WailsContext*) inctx;
+ ON_MAIN_THREAD(
+ [ctx Hide];
+ );
+}
+
+void Show(void *inctx) {
+ WailsContext *ctx = (__bridge WailsContext*) inctx;
+ ON_MAIN_THREAD(
+ [ctx Show];
+ );
+}
+
+void MessageDialog(void *inctx, const char* dialogType, const char* title, const char* message, const char* button1, const char* button2, const char* button3, const char* button4, const char* defaultButton, const char* cancelButton) {
+ WailsContext *ctx = (__bridge WailsContext*) inctx;
+ ON_MAIN_THREAD(
+ [ctx MessageDialog:dialogType :title :message :button1 :button2 :button3 :button4 :defaultButton :cancelButton];
+ )
+}
+
+void OpenFileDialog(void *inctx, const char* title, const char* defaultFilename, const char* defaultDirectory, int allowDirectories, int allowFiles, int canCreateDirectories, int treatPackagesAsDirectories, int resolveAliases, int showHiddenFiles, int allowMultipleSelection, const char* filters) {
+ WailsContext *ctx = (__bridge WailsContext*) inctx;
+ ON_MAIN_THREAD(
+ [ctx OpenFileDialog:title :defaultFilename :defaultDirectory :allowDirectories :allowFiles :canCreateDirectories :treatPackagesAsDirectories :resolveAliases :showHiddenFiles :allowMultipleSelection :filters];
+ )
+}
+
+void SaveFileDialog(void *inctx, const char* title, const char* defaultFilename, const char* defaultDirectory, int canCreateDirectories, int treatPackagesAsDirectories, int showHiddenFiles, const char* filters) {
+ WailsContext *ctx = (__bridge WailsContext*) inctx;
+ ON_MAIN_THREAD(
+ [ctx SaveFileDialog:title :defaultFilename :defaultDirectory :canCreateDirectories :treatPackagesAsDirectories :showHiddenFiles :filters];
+ )
+}
+
+
+
+
+void Run(void *inctx) {
+ WailsContext *ctx = (__bridge WailsContext*) inctx;
+ [NSApplication sharedApplication];
+ AppDelegate* delegate = [AppDelegate new];
+ [NSApp setDelegate:(id)delegate];
+ ctx.appdelegate = delegate;
+ delegate.mainWindow = ctx.mainWindow;
+ delegate.alwaysOnTop = ctx.alwaysOnTop;
+
+ [ctx loadRequest:@"wails://wails/"];
+
+ [NSApp run];
+ [ctx release];
+ NSLog(@"Here");
+}
diff --git a/v2/internal/frontend/desktop/darwin/WailsAlert.h b/v2/internal/frontend/desktop/darwin/WailsAlert.h
new file mode 100644
index 000000000..69e8ee170
--- /dev/null
+++ b/v2/internal/frontend/desktop/darwin/WailsAlert.h
@@ -0,0 +1,18 @@
+//
+// WailsAlert.h
+// test
+//
+// Created by Lea Anthony on 20/10/21.
+//
+
+#ifndef WailsAlert_h
+#define WailsAlert_h
+
+#import
+
+@interface WailsAlert : NSAlert
+- (void)addButton:(const char*)text :(const char*)defaultButton :(const char*)cancelButton;
+@end
+
+
+#endif /* WailsAlert_h */
diff --git a/v2/internal/frontend/desktop/darwin/WailsAlert.m b/v2/internal/frontend/desktop/darwin/WailsAlert.m
new file mode 100644
index 000000000..04105634c
--- /dev/null
+++ b/v2/internal/frontend/desktop/darwin/WailsAlert.m
@@ -0,0 +1,30 @@
+//
+// WailsAlert.m
+// test
+//
+// Created by Lea Anthony on 20/10/21.
+//
+
+#import
+
+#import "WailsAlert.h"
+
+@implementation WailsAlert
+
+- (void)addButton:(const char*)text :(const char*)defaultButton :(const char*)cancelButton {
+ if( text == nil ) {
+ return;
+ }
+ NSButton *button = [self addButtonWithTitle:[NSString stringWithUTF8String:text]];
+ if( defaultButton != nil && strcmp(text, defaultButton) == 0) {
+ [button setKeyEquivalent:@"\r"];
+ } else if( cancelButton != nil && strcmp(text, cancelButton) == 0) {
+ [button setKeyEquivalent:@"\033"];
+ } else {
+ [button setKeyEquivalent:@""];
+ }
+}
+
+@end
+
+
diff --git a/v2/internal/frontend/desktop/darwin/WailsContext.h b/v2/internal/frontend/desktop/darwin/WailsContext.h
new file mode 100644
index 000000000..c4b6e409b
--- /dev/null
+++ b/v2/internal/frontend/desktop/darwin/WailsContext.h
@@ -0,0 +1,74 @@
+//
+// WailsContext.h
+// test
+//
+// Created by Lea Anthony on 10/10/21.
+//
+
+#ifndef WailsContext_h
+#define WailsContext_h
+
+#import
+#import
+
+#define ON_MAIN_THREAD(str) dispatch_async(dispatch_get_main_queue(), ^{ str; });
+
+@interface WailsWindow : NSWindow
+- (BOOL)canBecomeKeyWindow;
+@end
+
+@interface WailsContext : NSObject
+
+@property (retain) WailsWindow* mainWindow;
+@property (retain) WKWebView* webview;
+@property (nonatomic, assign) id appdelegate;
+
+@property bool hideOnClose;
+@property bool shuttingDown;
+
+@property NSSize maxSize;
+@property NSSize minSize;
+
+@property (retain) NSEvent* mouseEvent;
+
+@property bool alwaysOnTop;
+@property bool maximised;
+
+@property bool debug;
+
+@property (retain) WKUserContentController* userContentController;
+
+@property (retain) NSMutableDictionary *urlRequests;
+
+- (void) CreateWindow:(int)width :(int)height :(bool)frameless :(bool)resizable :(bool)fullscreen :(bool)fullSizeContent :(bool)hideTitleBar :(bool)titlebarAppearsTransparent :(bool)hideTitle :(bool)useToolbar :(bool)hideToolbarSeparator :(bool)webviewIsTransparent :(bool)hideWindowOnClose :(const char *)appearance :(bool)windowIsTranslucent;
+- (void) SetSize:(int)width :(int)height;
+- (void) SetPosition:(int)x :(int) y;
+- (void) SetMinSize:(int)minWidth :(int)minHeight;
+- (void) SetMaxSize:(int)maxWidth :(int)maxHeight;
+- (void) SetTitle:(const char*)title;
+- (void) Center;
+- (void) Fullscreen;
+- (void) UnFullscreen;
+- (void) Minimise;
+- (void) UnMinimise;
+- (void) Maximise;
+- (void) UnMaximise;
+- (void) SetRGBA:(int)r :(int)g :(int)b :(int)a;
+- (void) HideMouse;
+- (void) ShowMouse;
+- (void) Hide;
+- (void) Show;
+
+-(void) MessageDialog :(const char*)dialogType :(const char*)title :(const char*)message :(const char*)button1 :(const char*)button2 :(const char*)button3 :(const char*)button4 :(const char*)defaultButton :(const char*)cancelButton;
+-(void) OpenFileDialog :(const char*)title :(const char*)defaultFilename :(const char*)defaultDirectory :(bool)allowDirectories :(bool)allowFiles :(bool)canCreateDirectories :(bool)treatPackagesAsDirectories :(bool)resolveAliases :(bool)showHiddenFiles :(bool)allowMultipleSelection :(const char*)filters;
+-(void) SaveFileDialog :(const char*)title :(const char*)defaultFilename :(const char*)defaultDirectory :(bool)canCreateDirectories :(bool)treatPackagesAsDirectories :(bool)showHiddenFiles :(const char*)filters;
+
+- (void) loadRequest:(NSString*)url;
+- (void) processURLResponse:(NSString *)url :(NSString *)contentType :(NSData*)data;
+- (void) ExecJS:(const char*)script;
+- (NSScreen*) getCurrentScreen;
+
+@end
+
+
+#endif /* WailsContext_h */
diff --git a/v2/internal/frontend/desktop/darwin/WailsContext.m b/v2/internal/frontend/desktop/darwin/WailsContext.m
new file mode 100644
index 000000000..967931f8c
--- /dev/null
+++ b/v2/internal/frontend/desktop/darwin/WailsContext.m
@@ -0,0 +1,527 @@
+//
+// WailsContext.m
+// test
+//
+// Created by Lea Anthony on 10/10/21.
+//
+
+#import
+#import
+#import "WailsContext.h"
+#import "WailsAlert.h"
+#import "WindowDelegate.h"
+#import "message.h"
+
+@implementation WailsWindow
+
+- (BOOL)canBecomeKeyWindow
+{
+ return YES;
+}
+
+@end
+
+@implementation WailsContext
+
+- (void) SetSize:(int)width :(int)height {
+
+ if (self.shuttingDown) return;
+
+ NSRect frame = [self.mainWindow frame];
+ frame.origin.y += frame.size.height - height;
+ frame.size.width = width;
+ frame.size.height = height;
+ [self.mainWindow setFrame:frame display:TRUE animate:FALSE];
+}
+
+- (void) SetPosition:(int)x :(int)y {
+
+ if (self.shuttingDown) return;
+
+ NSScreen* screen = [self getCurrentScreen];
+ NSRect windowFrame = [self.mainWindow frame];
+ NSRect screenFrame = [screen visibleFrame];
+ windowFrame.origin.x += screenFrame.origin.x + (float)x;
+ windowFrame.origin.y += (screenFrame.origin.y + screenFrame.size.height) - windowFrame.size.height - (float)y;
+
+ [self.mainWindow setFrame:windowFrame display:TRUE animate:FALSE];
+}
+
+- (void) SetMinSize:(int)minWidth :(int)minHeight {
+
+ if (self.shuttingDown) return;
+
+ NSSize size = { minWidth, minHeight };
+
+ self.minSize = size;
+
+ [self.mainWindow setMinSize:size];
+
+ [self adjustWindowSize];
+}
+
+
+- (void) SetMaxSize:(int)maxWidth :(int)maxHeight {
+
+ if (self.shuttingDown) return;
+
+ NSSize size = { FLT_MAX, FLT_MAX };
+
+ size.width = maxWidth > 0 ? maxWidth : FLT_MAX;
+ size.height = maxHeight > 0 ? maxHeight : FLT_MAX;
+
+ self.maxSize = size;
+
+ [self.mainWindow setMinSize:size];
+
+ [self adjustWindowSize];
+}
+
+
+- (void) adjustWindowSize {
+
+ if (self.shuttingDown) return;
+
+ NSRect currentFrame = [self.mainWindow frame];
+
+ if ( currentFrame.size.width > self.maxSize.width ) currentFrame.size.width = self.maxSize.width;
+ if ( currentFrame.size.width < self.minSize.width ) currentFrame.size.width = self.minSize.width;
+ if ( currentFrame.size.height > self.maxSize.height ) currentFrame.size.height = self.maxSize.height;
+ if ( currentFrame.size.height < self.minSize.height ) currentFrame.size.height = self.minSize.height;
+
+ [self.mainWindow setFrame:currentFrame display:TRUE animate:FALSE];
+
+}
+
+- (void) dealloc {
+ [super dealloc];
+ [self.appdelegate release];
+ [self.mainWindow release];
+ [self.mouseEvent release];
+ [self.userContentController release];
+ [self.urlRequests release];
+}
+
+- (NSScreen*) getCurrentScreen {
+ NSScreen* screen = [self.mainWindow screen];
+ if( screen == NULL ) {
+ screen = [NSScreen mainScreen];
+ }
+ return screen;
+}
+
+- (void) SetTitle:(const char *)title {
+ NSString *_title = [NSString stringWithUTF8String:title];
+ [self.mainWindow setTitle:_title];
+}
+
+- (void) Center {
+ [self.mainWindow center];
+}
+
+- (void) CreateWindow:(int)width :(int)height :(bool)frameless :(bool)resizable :(bool)fullscreen :(bool)fullSizeContent :(bool)hideTitleBar :(bool)titlebarAppearsTransparent :(bool)hideTitle :(bool)useToolbar :(bool)hideToolbarSeparator :(bool)webviewIsTransparent :(bool)hideWindowOnClose :(const char *)appearance :(bool)windowIsTranslucent {
+
+ self.urlRequests = [NSMutableDictionary new];
+
+ NSWindowStyleMask styleMask = NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable;
+
+ if (frameless) {
+ styleMask = NSWindowStyleMaskBorderless;
+ } else {
+ if (resizable) {
+ styleMask |= NSWindowStyleMaskResizable;
+ }
+ }
+ if (fullscreen) {
+ styleMask |= NSWindowStyleMaskFullScreen;
+ }
+
+ if( fullSizeContent || frameless || titlebarAppearsTransparent ) {
+ styleMask |= NSWindowStyleMaskFullSizeContentView;
+ }
+
+ self.mainWindow = [[[WailsWindow alloc] initWithContentRect:NSMakeRect(0, 0, width, height)
+ styleMask:styleMask backing:NSBackingStoreBuffered defer:NO]
+ autorelease];
+
+ if (frameless) {
+ return;
+ }
+
+ if (useToolbar) {
+ NSLog(@"Using Toolbar");
+ id toolbar = [[NSToolbar alloc] initWithIdentifier:@"wails.toolbar"];
+ [toolbar autorelease];
+ [toolbar setShowsBaselineSeparator:!hideToolbarSeparator];
+ [self.mainWindow setToolbar:toolbar];
+ }
+
+ [self.mainWindow setTitleVisibility:hideTitle];
+ [self.mainWindow setTitlebarAppearsTransparent:titlebarAppearsTransparent];
+ [self.mainWindow canBecomeKeyWindow];
+
+ id contentView = [self.mainWindow contentView];
+ if (windowIsTranslucent) {
+ NSVisualEffectView *effectView = [NSVisualEffectView alloc];
+ NSRect bounds = [contentView bounds];
+ [effectView initWithFrame:bounds];
+ [effectView setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
+ [effectView setBlendingMode:NSVisualEffectBlendingModeBehindWindow];
+ [effectView setState:NSVisualEffectStateActive];
+ [contentView addSubview:effectView positioned:NSWindowBelow relativeTo:nil];
+ }
+
+ if (appearance != nil) {
+ NSString *name = [NSString stringWithUTF8String:appearance];
+ NSAppearance *nsAppearance = [NSAppearance appearanceNamed:name];
+ [self.mainWindow setAppearance:nsAppearance];
+ }
+
+ // Set up min/max
+ NSSize maxSize = { FLT_MAX, FLT_MAX };
+ self.maxSize = maxSize;
+ NSSize minSize = { 0, 0 };
+ self.minSize = minSize;
+ [self adjustWindowSize];
+
+ WindowDelegate *windowDelegate = [WindowDelegate new];
+ windowDelegate.hideOnClose = hideWindowOnClose;
+ [self.mainWindow setDelegate:windowDelegate];
+
+ // Webview stuff here!
+ WKWebViewConfiguration *config = [WKWebViewConfiguration new];
+ config.suppressesIncrementalRendering = true;
+ [config setURLSchemeHandler:self forURLScheme:@"wails"];
+
+ [config.preferences setValue:[NSNumber numberWithBool:true] forKey:@"developerExtrasEnabled"];
+
+ WKUserContentController* userContentController = [WKUserContentController new];
+ [userContentController addScriptMessageHandler:self name:@"external"];
+ config.userContentController = userContentController;
+ self.userContentController = userContentController;
+ if (self.debug) {
+ [config.preferences setValue:@YES forKey:@"developerExtrasEnabled"];
+ } else {
+ // Disable default context menus
+ WKUserScript *initScript = [WKUserScript new];
+ [initScript initWithSource:@"window.wails.flags.disableWailsDefaultContextMenu = true;"
+ injectionTime:WKUserScriptInjectionTimeAtDocumentEnd
+ forMainFrameOnly:false];
+ [userContentController addUserScript:initScript];
+
+ }
+
+ self.webview = [WKWebView alloc];
+ CGRect init = { 0,0,0,0 };
+ [self.webview initWithFrame:init configuration:config];
+ [contentView addSubview:self.webview];
+ [self.webview setAutoresizingMask: NSViewWidthSizable|NSViewHeightSizable];
+ CGRect contentViewBounds = [contentView bounds];
+ [self.webview setFrame:contentViewBounds];
+
+ if (webviewIsTransparent) {
+ [self.webview setValue:[NSNumber numberWithBool:!webviewIsTransparent] forKey:@"drawsBackground"];
+ }
+
+ NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
+ [defaults setBool:FALSE forKey:@"NSAutomaticQuoteSubstitutionEnabled"];
+
+ // Mouse monitors
+ [NSEvent addLocalMonitorForEventsMatchingMask:NSEventMaskLeftMouseDown handler:^NSEvent * _Nullable(NSEvent * _Nonnull event) {
+ id window = [event window];
+ if (window == self.mainWindow) {
+ self.mouseEvent = event;
+ }
+ return event;
+ }];
+
+ [NSEvent addLocalMonitorForEventsMatchingMask:NSEventMaskLeftMouseUp handler:^NSEvent * _Nullable(NSEvent * _Nonnull event) {
+ id window = [event window];
+ if (window == self.mainWindow) {
+ self.mouseEvent = nil;
+ [self ShowMouse];
+ }
+ return event;
+ }];
+
+}
+
+- (void) loadRequest :(NSString*)url {
+ NSURL *wkUrl = [NSURL URLWithString:url];
+ NSURLRequest *wkRequest = [NSURLRequest requestWithURL:wkUrl];
+ [self.webview loadRequest:wkRequest];
+}
+
+- (void) SetRGBA:(int)r :(int)g :(int)b :(int)a {
+ float red = r/255;
+ float green = g/255;
+ float blue = b/255;
+ float alpha = a/255;
+
+ id colour = [NSColor colorWithCalibratedRed:red green:green blue:blue alpha:alpha ];
+
+ [self.mainWindow setBackgroundColor:colour];
+}
+
+- (void) HideMouse {
+ [NSCursor hide];
+}
+
+- (void) ShowMouse {
+ [NSCursor unhide];
+}
+
+- (bool) isFullScreen {
+ long mask = [self.mainWindow styleMask];
+ return (mask & NSWindowStyleMaskFullScreen) == NSWindowStyleMaskFullScreen;
+}
+
+// Fullscreen sets the main window to be fullscreen
+- (void) Fullscreen {
+ if( ! [self isFullScreen] ) {
+ [self.mainWindow toggleFullScreen:nil];
+ }
+}
+
+// UnFullscreen resets the main window after a fullscreen
+- (void) UnFullscreen {
+ if( [self isFullScreen] ) {
+ [self.mainWindow toggleFullScreen:nil];
+ }
+}
+
+- (void) Minimise {
+ [self.mainWindow miniaturize:nil];
+}
+
+- (void) UnMinimise {
+ [self.mainWindow deminiaturize:nil];
+}
+
+- (void) Hide {
+ [self.mainWindow orderOut:nil];
+}
+
+- (void) Show {
+ [self.mainWindow makeKeyAndOrderFront:nil];
+ [NSApp activateIgnoringOtherApps:YES];
+}
+
+- (void) Maximise {
+ if (! self.maximised) {
+ [self.mainWindow zoom:nil];
+ }
+}
+
+- (void) UnMaximise {
+ if (self.maximised) {
+ [self.mainWindow zoom:nil];
+ }
+}
+
+- (void) ExecJS:(const char*)script {
+ NSString *nsscript = [NSString stringWithUTF8String:script];
+ [self.webview evaluateJavaScript:nsscript completionHandler:nil];
+}
+
+- (void) processURLResponse:(NSString *)url :(NSString *)contentType :(NSData *)data {
+ id urlSchemeTask = self.urlRequests[url];
+ NSURL *nsurl = [NSURL URLWithString:url];
+
+ NSHTTPURLResponse *response = [NSHTTPURLResponse new];
+ NSMutableDictionary *headerFields = [NSMutableDictionary new];
+ headerFields[@"content-type"] = contentType;
+ [response initWithURL:nsurl statusCode:200 HTTPVersion:@"HTTP/1.1" headerFields:headerFields];
+ [urlSchemeTask didReceiveResponse:response];
+ [urlSchemeTask didReceiveData:data];
+ [urlSchemeTask didFinish];
+ [self.urlRequests removeObjectForKey:url];
+}
+
+- (void)webView:(nonnull WKWebView *)webView startURLSchemeTask:(nonnull id)urlSchemeTask {
+ // Do something
+ self.urlRequests[urlSchemeTask.request.URL.absoluteString] = urlSchemeTask;
+ processURLRequest(self, [urlSchemeTask.request.URL.absoluteString UTF8String]);
+}
+
+- (void)webView:(nonnull WKWebView *)webView stopURLSchemeTask:(nonnull id)urlSchemeTask {
+
+}
+
+- (void)userContentController:(nonnull WKUserContentController *)userContentController didReceiveScriptMessage:(nonnull WKScriptMessage *)message {
+ NSString *m = message.body;
+
+ // Check for drag
+ if ( [m isEqualToString:@"drag"] ) {
+ if( ! [self isFullScreen] ) {
+ if( self.mouseEvent != nil ) {
+ [self HideMouse];
+ ON_MAIN_THREAD(
+ [self.mainWindow performWindowDragWithEvent:self.mouseEvent];
+ );
+ }
+ return;
+ }
+ }
+
+ const char *_m = [m UTF8String];
+
+ processMessage(_m);
+}
+
+
+/***** Dialogs ******/
+-(void) MessageDialog :(const char*)dialogType :(const char*)title :(const char*)message :(const char*)button1 :(const char*)button2 :(const char*)button3 :(const char*)button4 :(const char*)defaultButton :(const char*)cancelButton {
+
+ WailsAlert *alert = [WailsAlert new];
+
+ int style = NSAlertStyleInformational;
+ if (dialogType != nil ) {
+ if( strcmp(dialogType, "warning") == 0 ) {
+ style = NSAlertStyleWarning;
+ }
+ if( strcmp(dialogType, "error") == 0) {
+ style = NSAlertStyleCritical;
+ }
+ }
+ [alert setAlertStyle:style];
+ if( strlen(title) > 0 ) {
+ [alert setMessageText:[NSString stringWithUTF8String:title]];
+ }
+ if( strlen(message) > 0 ) {
+ [alert setInformativeText:[NSString stringWithUTF8String:message]];
+ }
+
+ [alert addButton:button1 :defaultButton :cancelButton];
+ [alert addButton:button2 :defaultButton :cancelButton];
+ [alert addButton:button3 :defaultButton :cancelButton];
+ [alert addButton:button4 :defaultButton :cancelButton];
+
+ long response = [alert runModal];
+ int result;
+
+ if( response == NSAlertFirstButtonReturn ) {
+ result = 0;
+ }
+ else if( response == NSAlertSecondButtonReturn ) {
+ result = 1;
+ }
+ else if( response == NSAlertThirdButtonReturn ) {
+ result = 2;
+ } else {
+ result = 3;
+ }
+ processMessageDialogResponse(result);
+}
+
+-(void) OpenFileDialog :(const char*)title :(const char*)defaultFilename :(const char*)defaultDirectory :(bool)allowDirectories :(bool)allowFiles :(bool)canCreateDirectories :(bool)treatPackagesAsDirectories :(bool)resolveAliases :(bool)showHiddenFiles :(bool)allowMultipleSelection :(const char*)filters {
+
+
+ // Create the dialog
+ NSOpenPanel *dialog = [NSOpenPanel openPanel];
+
+ // Valid but appears to do nothing.... :/
+ if( strlen(title) > 0 ) {
+ [dialog setTitle:[NSString stringWithUTF8String:title]];
+ }
+
+ // Filters - semicolon delimited list of file extensions
+ if( allowFiles ) {
+ if( filters != nil && strlen(filters) > 0) {
+ NSString *filterString = [[NSString stringWithUTF8String:filters] stringByReplacingOccurrencesOfString:@"*." withString:@""];
+ filterString = [filterString stringByReplacingOccurrencesOfString:@" " withString:@""];
+ NSArray *filterList = [filterString componentsSeparatedByString:@";"];
+ [dialog setAllowedFileTypes:filterList];
+ } else {
+ [dialog setAllowsOtherFileTypes:true];
+ }
+ // Default Filename
+ if( defaultFilename != NULL && strlen(defaultFilename) > 0 ) {
+ [dialog setNameFieldStringValue:[NSString stringWithUTF8String:defaultFilename]];
+ }
+
+ [dialog setAllowsMultipleSelection: allowMultipleSelection];
+ [dialog setShowsHiddenFiles: showHiddenFiles];
+
+ }
+
+ // Default Directory
+ if( defaultDirectory != NULL && strlen(defaultDirectory) > 0 ) {
+ NSURL *url = [NSURL fileURLWithPath:[NSString stringWithUTF8String:defaultDirectory]];
+ [dialog setDirectoryURL:url];
+ }
+
+
+ // Setup Options
+ [dialog setCanChooseFiles: allowFiles];
+ [dialog setCanChooseDirectories: allowDirectories];
+ [dialog setCanCreateDirectories: canCreateDirectories];
+ [dialog setResolvesAliases: resolveAliases];
+ [dialog setTreatsFilePackagesAsDirectories: treatPackagesAsDirectories];
+
+ // Setup callback handler
+ [dialog beginSheetModalForWindow:self.mainWindow completionHandler:^(NSModalResponse returnCode) {
+ NSMutableArray *arr = [NSMutableArray new];
+ for (NSURL *url in [dialog URLs]) {
+ [arr addObject:[url path]];
+ }
+ NSData *jsonData = [NSJSONSerialization dataWithJSONObject:arr options:0 error:nil];
+ NSString *nsjson = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
+ processOpenFileDialogResponse([nsjson UTF8String]);
+ }];
+
+
+ [dialog runModal];
+
+}
+
+
+-(void) SaveFileDialog :(const char*)title :(const char*)defaultFilename :(const char*)defaultDirectory :(bool)canCreateDirectories :(bool)treatPackagesAsDirectories :(bool)showHiddenFiles :(const char*)filters; {
+
+
+ // Create the dialog
+ NSSavePanel *dialog = [NSOpenPanel savePanel];
+
+ // Valid but appears to do nothing.... :/
+ if( strlen(title) > 0 ) {
+ [dialog setTitle:[NSString stringWithUTF8String:title]];
+ }
+
+ // Filters - semicolon delimited list of file extensions
+ if( filters != nil && strlen(filters) > 0) {
+ NSString *filterString = [[NSString stringWithUTF8String:filters] stringByReplacingOccurrencesOfString:@"*." withString:@""];
+ filterString = [filterString stringByReplacingOccurrencesOfString:@" " withString:@""];
+ NSArray *filterList = [filterString componentsSeparatedByString:@";"];
+ [dialog setAllowedFileTypes:filterList];
+ } else {
+ [dialog setAllowsOtherFileTypes:true];
+ }
+ // Default Filename
+ if( defaultFilename != NULL && strlen(defaultFilename) > 0 ) {
+ [dialog setNameFieldStringValue:[NSString stringWithUTF8String:defaultFilename]];
+ }
+
+ // Default Directory
+ if( defaultDirectory != NULL && strlen(defaultDirectory) > 0 ) {
+ NSURL *url = [NSURL fileURLWithPath:[NSString stringWithUTF8String:defaultDirectory]];
+ [dialog setDirectoryURL:url];
+ }
+
+ // Setup Options
+ [dialog setCanCreateDirectories: canCreateDirectories];
+ [dialog setTreatsFilePackagesAsDirectories: treatPackagesAsDirectories];
+ [dialog setShowsHiddenFiles: showHiddenFiles];
+
+ // Setup callback handler
+ [dialog beginSheetModalForWindow:self.mainWindow completionHandler:^(NSModalResponse returnCode) {
+ NSURL *url = [dialog URL];
+ processSaveFileDialogResponse([url.path UTF8String]);
+ }];
+
+ [dialog runModal];
+
+}
+
+
+@end
+
diff --git a/v2/internal/frontend/desktop/darwin/WindowDelegate.h b/v2/internal/frontend/desktop/darwin/WindowDelegate.h
new file mode 100644
index 000000000..e4ba038d1
--- /dev/null
+++ b/v2/internal/frontend/desktop/darwin/WindowDelegate.h
@@ -0,0 +1,18 @@
+//
+// WindowDelegate.h
+// test
+//
+// Created by Lea Anthony on 10/10/21.
+//
+
+#ifndef WindowDelegate_h
+#define WindowDelegate_h
+
+@interface WindowDelegate : NSObject
+
+@property bool hideOnClose;
+
+@end
+
+
+#endif /* WindowDelegate_h */
diff --git a/v2/internal/frontend/desktop/darwin/WindowDelegate.m b/v2/internal/frontend/desktop/darwin/WindowDelegate.m
new file mode 100644
index 000000000..549413e45
--- /dev/null
+++ b/v2/internal/frontend/desktop/darwin/WindowDelegate.m
@@ -0,0 +1,23 @@
+//
+// WindowDelegate.m
+// test
+//
+// Created by Lea Anthony on 10/10/21.
+//
+
+#import
+#import
+#import "WindowDelegate.h"
+#import "message.h"
+
+@implementation WindowDelegate
+
+- (BOOL)windowShouldClose:(NSWindow *)sender {
+ [sender orderOut:nil];
+ if( self.hideOnClose == false ) {
+ processMessage("Q");
+ }
+ return !self.hideOnClose;
+}
+
+@end
diff --git a/v2/internal/frontend/desktop/darwin/browser.go b/v2/internal/frontend/desktop/darwin/browser.go
new file mode 100644
index 000000000..417501c8e
--- /dev/null
+++ b/v2/internal/frontend/desktop/darwin/browser.go
@@ -0,0 +1,14 @@
+//go:build darwin
+// +build darwin
+
+package darwin
+
+import (
+ "github.com/pkg/browser"
+)
+
+// BrowserOpenURL Use the default browser to open the url
+func (f *Frontend) BrowserOpenURL(url string) {
+ // Specific method implementation
+ _ = browser.OpenURL(url)
+}
diff --git a/v2/internal/frontend/desktop/darwin/calloc.go b/v2/internal/frontend/desktop/darwin/calloc.go
new file mode 100644
index 000000000..b1939900e
--- /dev/null
+++ b/v2/internal/frontend/desktop/darwin/calloc.go
@@ -0,0 +1,32 @@
+package darwin
+
+/*
+#include
+*/
+import "C"
+import "unsafe"
+
+// Calloc handles alloc/dealloc of C data
+type Calloc struct {
+ pool []unsafe.Pointer
+}
+
+// NewCalloc creates a new allocator
+func NewCalloc() Calloc {
+ return Calloc{}
+}
+
+// String creates a new C string and retains a reference to it
+func (c Calloc) String(in string) *C.char {
+ result := C.CString(in)
+ c.pool = append(c.pool, unsafe.Pointer(result))
+ return result
+}
+
+// Free frees all allocated C memory
+func (c Calloc) Free() {
+ for _, str := range c.pool {
+ C.free(str)
+ }
+ c.pool = []unsafe.Pointer{}
+}
diff --git a/v2/internal/frontend/desktop/darwin/dialog.go b/v2/internal/frontend/desktop/darwin/dialog.go
new file mode 100644
index 000000000..9e359f249
--- /dev/null
+++ b/v2/internal/frontend/desktop/darwin/dialog.go
@@ -0,0 +1,185 @@
+//go:build darwin
+// +build darwin
+
+package darwin
+
+/*
+#cgo CFLAGS: -x objective-c
+#cgo LDFLAGS: -framework Foundation -framework Cocoa -framework WebKit
+#import
+#import "Application.h"
+#import "WailsContext.h"
+*/
+import "C"
+import (
+ "encoding/json"
+ "fmt"
+ "strings"
+ "sync"
+
+ "github.com/leaanthony/slicer"
+ "github.com/wailsapp/wails/v2/internal/frontend"
+)
+
+// Obj-C dialog methods send the response to this channel
+var messageDialogResponse = make(chan int)
+var openFileDialogResponse = make(chan string)
+var saveFileDialogResponse = make(chan string)
+var dialogLock sync.Mutex
+
+// OpenDirectoryDialog prompts the user to select a directory
+func (f *Frontend) OpenDirectoryDialog(options frontend.OpenDialogOptions) (string, error) {
+ results, err := f.openDialog(&options, false, false, true)
+ if err != nil {
+ return "", err
+ }
+ var selected string
+ if len(results) > 0 {
+ selected = results[0]
+ }
+ return selected, nil
+}
+
+func (f *Frontend) openDialog(options *frontend.OpenDialogOptions, multiple bool, allowfiles bool, allowdirectories bool) ([]string, error) {
+ dialogLock.Lock()
+ defer dialogLock.Unlock()
+
+ c := NewCalloc()
+ defer c.Free()
+ title := c.String(options.Title)
+ defaultFilename := c.String(options.DefaultFilename)
+ defaultDirectory := c.String(options.DefaultDirectory)
+ allowDirectories := bool2Cint(allowdirectories)
+ allowFiles := bool2Cint(allowfiles)
+ canCreateDirectories := bool2Cint(options.CanCreateDirectories)
+ treatPackagesAsDirectories := bool2Cint(options.TreatPackagesAsDirectories)
+ resolveAliases := bool2Cint(options.ResolvesAliases)
+ showHiddenFiles := bool2Cint(options.ShowHiddenFiles)
+ allowMultipleFileSelection := bool2Cint(multiple)
+
+ var filterStrings slicer.StringSlicer
+ if options.Filters != nil {
+ for _, filter := range options.Filters {
+ thesePatterns := strings.Split(filter.Pattern, ";")
+ for _, pattern := range thesePatterns {
+ pattern = strings.TrimSpace(pattern)
+ if pattern != "" {
+ filterStrings.Add(pattern)
+ }
+ }
+ }
+ filterStrings.Deduplicate()
+ }
+ filters := filterStrings.Join(";")
+ C.OpenFileDialog(f.mainWindow.context, title, defaultFilename, defaultDirectory, allowDirectories, allowFiles, canCreateDirectories, treatPackagesAsDirectories, resolveAliases, showHiddenFiles, allowMultipleFileSelection, c.String(filters))
+
+ var result = <-openFileDialogResponse
+
+ var parsedResults []string
+ err := json.Unmarshal([]byte(result), &parsedResults)
+
+ return parsedResults, err
+}
+
+// OpenFileDialog prompts the user to select a file
+func (f *Frontend) OpenFileDialog(options frontend.OpenDialogOptions) (string, error) {
+ results, err := f.openDialog(&options, false, options.AllowFiles, options.AllowDirectories)
+ if err != nil {
+ return "", err
+ }
+ var selected string
+ if len(results) > 0 {
+ selected = results[0]
+ }
+ return selected, nil
+}
+
+// OpenMultipleFilesDialog prompts the user to select a file
+func (f *Frontend) OpenMultipleFilesDialog(options frontend.OpenDialogOptions) ([]string, error) {
+ return f.openDialog(&options, true, options.AllowFiles, options.AllowDirectories)
+}
+
+// SaveFileDialog prompts the user to select a file
+func (f *Frontend) SaveFileDialog(options frontend.SaveDialogOptions) (string, error) {
+ dialogLock.Lock()
+ defer dialogLock.Unlock()
+
+ c := NewCalloc()
+ defer c.Free()
+ title := c.String(options.Title)
+ defaultFilename := c.String(options.DefaultFilename)
+ defaultDirectory := c.String(options.DefaultDirectory)
+ canCreateDirectories := bool2Cint(options.CanCreateDirectories)
+ treatPackagesAsDirectories := bool2Cint(options.TreatPackagesAsDirectories)
+ showHiddenFiles := bool2Cint(options.ShowHiddenFiles)
+
+ var filterStrings slicer.StringSlicer
+ if options.Filters != nil {
+ for _, filter := range options.Filters {
+ thesePatterns := strings.Split(filter.Pattern, ";")
+ for _, pattern := range thesePatterns {
+ pattern = strings.TrimSpace(pattern)
+ if pattern != "" {
+ filterStrings.Add(pattern)
+ }
+ }
+ }
+ filterStrings.Deduplicate()
+ }
+ filters := filterStrings.Join(";")
+ C.SaveFileDialog(f.mainWindow.context, title, defaultFilename, defaultDirectory, canCreateDirectories, treatPackagesAsDirectories, showHiddenFiles, c.String(filters))
+
+ var result = <-saveFileDialogResponse
+
+ return result, nil
+}
+
+// MessageDialog show a message dialog to the user
+func (f *Frontend) MessageDialog(options frontend.MessageDialogOptions) (string, error) {
+ dialogLock.Lock()
+ defer dialogLock.Unlock()
+
+ c := NewCalloc()
+ defer c.Free()
+ dialogType := c.String(string(options.Type))
+ title := c.String(options.Title)
+ message := c.String(options.Message)
+ defaultButton := c.String(options.DefaultButton)
+ cancelButton := c.String(options.CancelButton)
+ const MaxButtons = 4
+ var buttons [MaxButtons]*C.char
+ for index, buttonText := range options.Buttons {
+ if index == MaxButtons {
+ return "", fmt.Errorf("max %d buttons supported (%d given)", MaxButtons, len(options.Buttons))
+ }
+ buttons[index] = c.String(buttonText)
+ }
+
+ C.MessageDialog(f.mainWindow.context, dialogType, title, message, buttons[0], buttons[1], buttons[2], buttons[3], defaultButton, cancelButton)
+
+ var result = <-messageDialogResponse
+
+ selectedC := buttons[result]
+ var selected string
+ if selectedC != nil {
+ selected = options.Buttons[result]
+ }
+ return selected, nil
+}
+
+//export processMessageDialogResponse
+func processMessageDialogResponse(selection int) {
+ messageDialogResponse <- selection
+}
+
+//export processOpenFileDialogResponse
+func processOpenFileDialogResponse(cselection *C.char) {
+ selection := C.GoString(cselection)
+ openFileDialogResponse <- selection
+}
+
+//export processSaveFileDialogResponse
+func processSaveFileDialogResponse(cselection *C.char) {
+ selection := C.GoString(cselection)
+ saveFileDialogResponse <- selection
+}
diff --git a/v2/internal/frontend/desktop/darwin/frontend.go b/v2/internal/frontend/desktop/darwin/frontend.go
new file mode 100644
index 000000000..04f366f86
--- /dev/null
+++ b/v2/internal/frontend/desktop/darwin/frontend.go
@@ -0,0 +1,306 @@
+//go:build darwin
+// +build darwin
+
+package darwin
+
+/*
+#cgo CFLAGS: -x objective-c
+#cgo LDFLAGS: -framework Foundation -framework Cocoa -framework WebKit
+#import
+#import "Application.h"
+#import "WailsContext.h"
+
+#include
+*/
+import "C"
+import (
+ "context"
+ "encoding/json"
+ "html/template"
+ "log"
+ "strconv"
+ "strings"
+ "unsafe"
+
+ "github.com/wailsapp/wails/v2/internal/binding"
+ "github.com/wailsapp/wails/v2/internal/frontend"
+ "github.com/wailsapp/wails/v2/internal/frontend/assetserver"
+ "github.com/wailsapp/wails/v2/internal/logger"
+ "github.com/wailsapp/wails/v2/pkg/options"
+)
+
+type request struct {
+ url *C.char
+ ctx unsafe.Pointer
+}
+
+var messageBuffer = make(chan string, 100)
+var requestBuffer = make(chan *request, 100)
+
+type Frontend struct {
+
+ // Context
+ ctx context.Context
+
+ frontendOptions *options.App
+ logger *logger.Logger
+ debug bool
+
+ // Assets
+ assets *assetserver.DesktopAssetServer
+
+ // main window handle
+ mainWindow *Window
+ minWidth, minHeight, maxWidth, maxHeight int
+ bindings *binding.Bindings
+ dispatcher frontend.Dispatcher
+ servingFromDisk bool
+}
+
+func NewFrontend(ctx context.Context, appoptions *options.App, myLogger *logger.Logger, appBindings *binding.Bindings, dispatcher frontend.Dispatcher) *Frontend {
+
+ result := &Frontend{
+ frontendOptions: appoptions,
+ logger: myLogger,
+ bindings: appBindings,
+ dispatcher: dispatcher,
+ ctx: ctx,
+ minHeight: appoptions.MinHeight,
+ minWidth: appoptions.MinWidth,
+ maxHeight: appoptions.MaxHeight,
+ maxWidth: appoptions.MaxWidth,
+ }
+
+ // Check if we have been given a directory to serve assets from.
+ // If so, this means we are in dev mode and are serving assets off disk.
+ // We indicate this through the `servingFromDisk` flag to ensure requests
+ // aren't cached by WebView2 in dev mode
+ _assetdir := ctx.Value("assetdir")
+ if _assetdir != nil {
+ result.servingFromDisk = true
+ }
+
+ bindingsJSON, err := appBindings.ToJSON()
+ if err != nil {
+ log.Fatal(err)
+ }
+ assets, err := assetserver.NewDesktopAssetServer(ctx, appoptions.Assets, bindingsJSON)
+ if err != nil {
+ log.Fatal(err)
+ }
+ result.assets = assets
+
+ go result.startMessageProcessor()
+ go result.startRequestProcessor()
+
+ return result
+}
+
+func (f *Frontend) startMessageProcessor() {
+ for message := range messageBuffer {
+ f.processMessage(message)
+ }
+}
+func (f *Frontend) startRequestProcessor() {
+ for request := range requestBuffer {
+ f.processRequest(request)
+ }
+}
+
+func (f *Frontend) WindowReload() {
+ f.ExecJS("runtime.WindowReload();")
+}
+
+func (f *Frontend) Run(ctx context.Context) error {
+
+ f.ctx = context.WithValue(ctx, "frontend", f)
+
+ var _debug = ctx.Value("debug")
+ if _debug != nil {
+ f.debug = _debug.(bool)
+ }
+
+ mainWindow := NewWindow(f.frontendOptions, f.debug)
+ f.mainWindow = mainWindow
+ f.mainWindow.Center()
+
+ go func() {
+ if f.frontendOptions.OnStartup != nil {
+ f.frontendOptions.OnStartup(f.ctx)
+ }
+ }()
+ mainWindow.Run()
+ return nil
+}
+
+func (f *Frontend) WindowCenter() {
+ f.mainWindow.Center()
+}
+
+func (f *Frontend) WindowSetPos(x, y int) {
+ f.mainWindow.SetPos(x, y)
+}
+func (f *Frontend) WindowGetPos() (int, int) {
+ return f.mainWindow.Pos()
+}
+
+func (f *Frontend) WindowSetSize(width, height int) {
+ f.mainWindow.SetSize(width, height)
+}
+
+func (f *Frontend) WindowGetSize() (int, int) {
+ return f.mainWindow.Size()
+}
+
+func (f *Frontend) WindowSetTitle(title string) {
+ f.mainWindow.SetTitle(title)
+}
+
+func (f *Frontend) WindowFullscreen() {
+ f.mainWindow.SetMaxSize(0, 0)
+ f.mainWindow.SetMinSize(0, 0)
+ f.mainWindow.Fullscreen()
+}
+
+func (f *Frontend) WindowUnFullscreen() {
+ f.mainWindow.UnFullscreen()
+ f.mainWindow.SetMaxSize(f.maxWidth, f.maxHeight)
+ f.mainWindow.SetMinSize(f.minWidth, f.minHeight)
+}
+
+func (f *Frontend) WindowShow() {
+ f.mainWindow.Show()
+}
+
+func (f *Frontend) WindowHide() {
+ f.mainWindow.Hide()
+}
+func (f *Frontend) WindowMaximise() {
+ f.mainWindow.Maximise()
+}
+func (f *Frontend) WindowUnmaximise() {
+ f.mainWindow.UnMaximise()
+}
+func (f *Frontend) WindowMinimise() {
+ f.mainWindow.Minimise()
+}
+func (f *Frontend) WindowUnminimise() {
+ f.mainWindow.UnMinimise()
+}
+
+func (f *Frontend) WindowSetMinSize(width int, height int) {
+ f.minWidth = width
+ f.minHeight = height
+ f.mainWindow.SetMinSize(width, height)
+}
+func (f *Frontend) WindowSetMaxSize(width int, height int) {
+ f.maxWidth = width
+ f.maxHeight = height
+ f.mainWindow.SetMaxSize(width, height)
+}
+
+func (f *Frontend) WindowSetRGBA(col *options.RGBA) {
+ if col == nil {
+ return
+ }
+ f.mainWindow.SetRGBA(col.R, col.G, col.B, col.A)
+}
+
+func (f *Frontend) Quit() {
+ f.mainWindow.Quit()
+}
+
+type EventNotify struct {
+ Name string `json:"name"`
+ Data []interface{} `json:"data"`
+}
+
+func (f *Frontend) Notify(name string, data ...interface{}) {
+ notification := EventNotify{
+ Name: name,
+ Data: data,
+ }
+ payload, err := json.Marshal(notification)
+ if err != nil {
+ f.logger.Error(err.Error())
+ return
+ }
+ f.ExecJS(`window.wails.EventsNotify('` + template.JSEscapeString(string(payload)) + `');`)
+}
+
+func (f *Frontend) processMessage(message string) {
+ if message == "drag" {
+ err := f.startDrag()
+ if err != nil {
+ f.logger.Error(err.Error())
+ }
+ return
+ }
+ result, err := f.dispatcher.ProcessMessage(message, f)
+ if err != nil {
+ f.logger.Error(err.Error())
+ f.Callback(result)
+ return
+ }
+ if result == "" {
+ return
+ }
+
+ switch result[0] {
+ case 'c':
+ // Callback from a method call
+ f.Callback(result[1:])
+ default:
+ f.logger.Info("Unknown message returned from dispatcher: %+v", result)
+ }
+}
+
+func (f *Frontend) Callback(message string) {
+ f.ExecJS(`window.wails.Callback(` + strconv.Quote(message) + `);`)
+}
+
+func (f *Frontend) startDrag() error {
+ //if !w32.ReleaseCapture() {
+ // return fmt.Errorf("unable to release mouse capture")
+ //}
+ //w32.SendMessage(f.mainWindow.Handle(), w32.WM_NCLBUTTONDOWN, w32.HTCAPTION, 0)
+ return nil
+}
+
+func (f *Frontend) ExecJS(js string) {
+ f.mainWindow.ExecJS(js)
+}
+
+func (f *Frontend) processRequest(r *request) {
+ url := C.GoString(r.url)
+ url = strings.TrimPrefix(url, "wails://wails")
+ if !strings.HasPrefix(url, "/") {
+ return
+ }
+ _contents, _mimetype, err := f.assets.Load(url)
+ if err != nil {
+ f.logger.Error(err.Error())
+ //TODO: Handle errors
+ return
+ }
+ data := C.CString(string(_contents))
+ defer C.free(unsafe.Pointer(data))
+ mimetype := C.CString(_mimetype)
+ defer C.free(unsafe.Pointer(mimetype))
+
+ C.ProcessURLResponse(r.ctx, r.url, mimetype, data, C.int(len(_contents)))
+}
+
+//export processMessage
+func processMessage(message *C.char) {
+ goMessage := C.GoString(message)
+ messageBuffer <- goMessage
+}
+
+//export processURLRequest
+func processURLRequest(ctx unsafe.Pointer, url *C.char) {
+ requestBuffer <- &request{
+ url: url,
+ ctx: ctx,
+ }
+}
diff --git a/v2/internal/frontend/desktop/darwin/main.m b/v2/internal/frontend/desktop/darwin/main.m
new file mode 100644
index 000000000..d605d8282
--- /dev/null
+++ b/v2/internal/frontend/desktop/darwin/main.m
@@ -0,0 +1,56 @@
+//go:build ignore
+// main.m
+// test
+//
+// Created by Lea Anthony on 10/10/21.
+//
+
+// ****** This file is used for testing purposes only ******
+
+#import
+#import "Application.h"
+
+void processMessage(const char*t) {
+ NSLog(@"processMessage called");
+
+}
+
+void processMessageDialogResponse(int t) {
+ NSLog(@"processMessage called");
+}
+
+void processOpenFileDialogResponse(const char *t) {
+ NSLog(@"processMessage called %s", t);
+}
+
+void processURLRequest(void *ctx, const char* url) {
+ NSLog(@"processURLRequest called");
+ const char myByteArray[] = { 0x3c,0x68,0x31,0x3e,0x48,0x65,0x6c,0x6c,0x6f,0x20,0x57,0x6f,0x72,0x6c,0x64,0x21,0x3c,0x2f,0x68,0x31,0x3e };
+ ProcessURLResponse(ctx, url, "text/html", myByteArray, 21);
+}
+
+int main(int argc, const char * argv[]) {
+ // insert code here...
+ int frameless = 0;
+ int resizable = 1;
+ int fullscreen = 0;
+ int fullSizeContent = 1;
+ int hideTitleBar = 0;
+ int titlebarAppearsTransparent = 1;
+ int hideTitle = 0;
+ int useToolbar = 1;
+ int hideToolbarSeparator = 1;
+ int webviewIsTransparent = 0;
+ int alwaysOnTop = 1;
+ int hideWindowOnClose = 0;
+ const char* appearance = "NSAppearanceNameDarkAqua";
+ int windowIsTranslucent = 1;
+ int debug = 1;
+ WailsContext *result = Create("OI OI!",400,400, frameless, resizable, fullscreen, fullSizeContent, hideTitleBar, titlebarAppearsTransparent, hideTitle, useToolbar, hideToolbarSeparator, webviewIsTransparent, alwaysOnTop, hideWindowOnClose, appearance, windowIsTranslucent, debug);
+ SetRGBA(result, 255, 0, 0, 255);
+
+
+
+ Run((void*)CFBridgingRetain(result));
+ return 0;
+}
diff --git a/v2/internal/frontend/desktop/darwin/menu.go b/v2/internal/frontend/desktop/darwin/menu.go
new file mode 100644
index 000000000..3ccb156cf
--- /dev/null
+++ b/v2/internal/frontend/desktop/darwin/menu.go
@@ -0,0 +1,98 @@
+//go:build darwin
+// +build darwin
+
+package darwin
+
+import (
+ "github.com/wailsapp/wails/v2/pkg/menu"
+)
+
+//func (w *Window) SetApplicationMenu(menu *menu.Menu) {
+//w.applicationMenu = menu
+//processMenu(w, menu)
+//}
+
+//func processMenu(window *Window, menu *menu.Menu) {
+//mainMenu := window.NewMenu()
+//for _, menuItem := range menu.Items {
+// submenu := mainMenu.AddSubMenu(menuItem.Label)
+// for _, menuItem := range menuItem.SubMenu.Items {
+// processMenuItem(submenu, menuItem)
+// }
+//}
+//mainMenu.Show()
+//}
+
+//func processMenuItem(parent *winc.MenuItem, menuItem *menu.MenuItem) {
+// if menuItem.Hidden {
+// return
+// }
+// switch menuItem.Type {
+// case menu.SeparatorType:
+// parent.AddSeparator()
+// case menu.TextType:
+// shortcut := acceleratorToWincShortcut(menuItem.Accelerator)
+// newItem := parent.AddItem(menuItem.Label, shortcut)
+// if menuItem.Tooltip != "" {
+// newItem.SetToolTip(menuItem.Tooltip)
+// }
+// if menuItem.Click != nil {
+// newItem.OnClick().Bind(func(e *winc.Event) {
+// menuItem.Click(&menu.CallbackData{
+// MenuItem: menuItem,
+// })
+// })
+// }
+// newItem.SetEnabled(!menuItem.Disabled)
+//
+// case menu.CheckboxType:
+// shortcut := acceleratorToWincShortcut(menuItem.Accelerator)
+// newItem := parent.AddItem(menuItem.Label, shortcut)
+// newItem.SetCheckable(true)
+// newItem.SetChecked(menuItem.Checked)
+// if menuItem.Tooltip != "" {
+// newItem.SetToolTip(menuItem.Tooltip)
+// }
+// if menuItem.Click != nil {
+// newItem.OnClick().Bind(func(e *winc.Event) {
+// toggleCheckBox(menuItem)
+// menuItem.Click(&menu.CallbackData{
+// MenuItem: menuItem,
+// })
+// })
+// }
+// newItem.SetEnabled(!menuItem.Disabled)
+// addCheckBoxToMap(menuItem, newItem)
+// case menu.RadioType:
+// shortcut := acceleratorToWincShortcut(menuItem.Accelerator)
+// newItem := parent.AddItemRadio(menuItem.Label, shortcut)
+// newItem.SetCheckable(true)
+// newItem.SetChecked(menuItem.Checked)
+// if menuItem.Tooltip != "" {
+// newItem.SetToolTip(menuItem.Tooltip)
+// }
+// if menuItem.Click != nil {
+// newItem.OnClick().Bind(func(e *winc.Event) {
+// toggleRadioItem(menuItem)
+// menuItem.Click(&menu.CallbackData{
+// MenuItem: menuItem,
+// })
+// })
+// }
+// newItem.SetEnabled(!menuItem.Disabled)
+// addRadioItemToMap(menuItem, newItem)
+// case menu.SubmenuType:
+// submenu := parent.AddSubMenu(menuItem.Label)
+// for _, menuItem := range menuItem.SubMenu.Items {
+// processMenuItem(submenu, menuItem)
+// }
+// }
+//}
+
+func (f *Frontend) MenuSetApplicationMenu(menu *menu.Menu) {
+ //f.mainWindow.SetApplicationMenu(menu)
+}
+
+func (f *Frontend) MenuUpdateApplicationMenu() {
+ //processMenu(f.mainWindow, f.mainWindow.applicationMenu)
+}
diff --git a/v2/internal/frontend/desktop/darwin/message.h b/v2/internal/frontend/desktop/darwin/message.h
new file mode 100644
index 000000000..51f242ccc
--- /dev/null
+++ b/v2/internal/frontend/desktop/darwin/message.h
@@ -0,0 +1,28 @@
+//
+// message.h
+// test
+//
+// Created by Lea Anthony on 14/10/21.
+//
+
+#ifndef export_h
+#define export_h
+
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+void processMessage(const char *);
+void processURLRequest(void*, const char *);
+void processMessageDialogResponse(int);
+void processOpenFileDialogResponse(const char*);
+void processSaveFileDialogResponse(const char*);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* export_h */
diff --git a/v2/internal/frontend/desktop/darwin/window.go b/v2/internal/frontend/desktop/darwin/window.go
new file mode 100644
index 000000000..b12937d42
--- /dev/null
+++ b/v2/internal/frontend/desktop/darwin/window.go
@@ -0,0 +1,187 @@
+package darwin
+
+/*
+#cgo CFLAGS: -x objective-c
+#cgo LDFLAGS: -framework Foundation -framework Cocoa -framework WebKit
+#import
+#import "Application.h"
+#import "WailsContext.h"
+
+#include
+*/
+import "C"
+import (
+ "log"
+ "runtime"
+ "strconv"
+ "strings"
+ "unsafe"
+
+ "github.com/wailsapp/wails/v2/pkg/options"
+)
+
+func init() {
+ runtime.LockOSThread()
+}
+
+type Window struct {
+ context unsafe.Pointer
+}
+
+func bool2Cint(value bool) C.int {
+ if value {
+ return C.int(1)
+ }
+ return C.int(0)
+}
+
+func NewWindow(frontendOptions *options.App, debugMode bool) *Window {
+
+ c := NewCalloc()
+ defer c.Free()
+
+ frameless := bool2Cint(frontendOptions.Frameless)
+ resizable := bool2Cint(!frontendOptions.DisableResize)
+ fullscreen := bool2Cint(frontendOptions.Fullscreen)
+ alwaysOnTop := bool2Cint(frontendOptions.AlwaysOnTop)
+ hideWindowOnClose := bool2Cint(frontendOptions.HideWindowOnClose)
+ debug := bool2Cint(debugMode)
+ alpha := C.int(frontendOptions.RGBA.A)
+ red := C.int(frontendOptions.RGBA.R)
+ green := C.int(frontendOptions.RGBA.G)
+ blue := C.int(frontendOptions.RGBA.B)
+
+ var fullSizeContent, hideTitleBar, hideTitle, useToolbar, webviewIsTransparent C.int
+ var titlebarAppearsTransparent, hideToolbarSeparator, windowIsTranslucent C.int
+ var appearance, title *C.char
+
+ width := C.int(frontendOptions.Width)
+ height := C.int(frontendOptions.Height)
+
+ title = c.String(frontendOptions.Title)
+
+ if frontendOptions.Mac != nil {
+ mac := frontendOptions.Mac
+ if mac.TitleBar != nil {
+ fullSizeContent = bool2Cint(mac.TitleBar.FullSizeContent)
+ hideTitleBar = bool2Cint(mac.TitleBar.HideTitleBar)
+ hideTitle = bool2Cint(mac.TitleBar.HideTitle)
+ useToolbar = bool2Cint(mac.TitleBar.UseToolbar)
+ titlebarAppearsTransparent = bool2Cint(mac.TitleBar.TitlebarAppearsTransparent)
+ hideToolbarSeparator = bool2Cint(mac.TitleBar.HideToolbarSeparator)
+ }
+ windowIsTranslucent = bool2Cint(mac.WindowIsTranslucent)
+ webviewIsTransparent = bool2Cint(mac.WebviewIsTransparent)
+
+ appearance = c.String(string(mac.Appearance))
+ }
+ var context *C.WailsContext = C.Create(title, width, height, frameless, resizable, fullscreen, fullSizeContent, hideTitleBar, titlebarAppearsTransparent, hideTitle, useToolbar, hideToolbarSeparator, webviewIsTransparent, alwaysOnTop, hideWindowOnClose, appearance, windowIsTranslucent, debug)
+
+ C.SetRGBA(unsafe.Pointer(context), red, green, blue, alpha)
+
+ return &Window{
+ context: unsafe.Pointer(context),
+ }
+}
+
+func (w *Window) Center() {
+ C.Center(w.context)
+}
+
+func (w *Window) Run() {
+ C.Run(w.context)
+ println("I exited!")
+}
+
+func (w *Window) Quit() {
+ C.Quit(w.context)
+}
+
+func (w *Window) SetRGBA(r uint8, g uint8, b uint8, a uint8) {
+ C.SetRGBA(w.context, C.int(r), C.int(g), C.int(b), C.int(a))
+}
+
+func (w *Window) ExecJS(js string) {
+ _js := C.CString(js)
+ C.ExecJS(w.context, _js)
+ C.free(unsafe.Pointer(_js))
+}
+
+func (w *Window) SetPos(x int, y int) {
+ C.SetPosition(w.context, C.int(x), C.int(y))
+}
+
+func (w *Window) SetSize(width int, height int) {
+ C.SetSize(w.context, C.int(width), C.int(height))
+}
+
+func (w *Window) SetTitle(title string) {
+ t := C.CString(title)
+ C.SetTitle(w.context, t)
+ C.free(unsafe.Pointer(t))
+}
+
+func (w *Window) Maximise() {
+ C.Maximise(w.context)
+}
+
+func (w *Window) UnMaximise() {
+ C.UnMaximise(w.context)
+}
+
+func (w *Window) Minimise() {
+ C.Minimise(w.context)
+}
+
+func (w *Window) UnMinimise() {
+ C.UnMinimise(w.context)
+}
+
+func (w *Window) SetMinSize(width int, height int) {
+ C.SetMinSize(w.context, C.int(width), C.int(height))
+}
+
+func (w *Window) SetMaxSize(width int, height int) {
+ C.SetMaxSize(w.context, C.int(width), C.int(height))
+}
+
+func (w *Window) Fullscreen() {
+ C.Fullscreen(w.context)
+}
+
+func (w *Window) UnFullscreen() {
+ C.UnFullscreen(w.context)
+}
+
+func (w *Window) Show() {
+ C.Show(w.context)
+}
+
+func (w *Window) Hide() {
+ C.Hide(w.context)
+}
+
+func parseIntDuo(temp string) (int, int) {
+ split := strings.Split(temp, ",")
+ x, err := strconv.Atoi(split[0])
+ if err != nil {
+ log.Fatal(err)
+ }
+ y, err := strconv.Atoi(split[1])
+ if err != nil {
+ log.Fatal(err)
+ }
+ return x, y
+}
+
+func (w *Window) Pos() (int, int) {
+ var _result *C.char = C.GetPos(w.context)
+ temp := C.GoString(_result)
+ return parseIntDuo(temp)
+}
+
+func (w *Window) Size() (int, int) {
+ var _result *C.char = C.GetSize(w.context)
+ temp := C.GoString(_result)
+ return parseIntDuo(temp)
+}
diff --git a/v2/internal/frontend/desktop/desktop_darwin.go b/v2/internal/frontend/desktop/desktop_darwin.go
new file mode 100644
index 000000000..fbf977fd5
--- /dev/null
+++ b/v2/internal/frontend/desktop/desktop_darwin.go
@@ -0,0 +1,19 @@
+//go:build darwin
+
+package desktop
+
+import (
+ "context"
+
+ "github.com/wailsapp/wails/v2/internal/frontend/desktop/darwin"
+
+ "github.com/wailsapp/wails/v2/internal/binding"
+ "github.com/wailsapp/wails/v2/internal/frontend"
+
+ "github.com/wailsapp/wails/v2/internal/logger"
+ "github.com/wailsapp/wails/v2/pkg/options"
+)
+
+func NewFrontend(ctx context.Context, appoptions *options.App, logger *logger.Logger, appBindings *binding.Bindings, dispatcher frontend.Dispatcher) frontend.Frontend {
+ return darwin.NewFrontend(ctx, appoptions, logger, appBindings, dispatcher)
+}
diff --git a/v2/internal/frontend/desktop/desktop_windows.go b/v2/internal/frontend/desktop/desktop_windows.go
new file mode 100644
index 000000000..f3c8e05d9
--- /dev/null
+++ b/v2/internal/frontend/desktop/desktop_windows.go
@@ -0,0 +1,16 @@
+//go:build windows
+
+package desktop
+
+import (
+ "context"
+ "github.com/wailsapp/wails/v2/internal/binding"
+ "github.com/wailsapp/wails/v2/internal/frontend"
+ "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows"
+ "github.com/wailsapp/wails/v2/internal/logger"
+ "github.com/wailsapp/wails/v2/pkg/options"
+)
+
+func NewFrontend(ctx context.Context, appoptions *options.App, logger *logger.Logger, appBindings *binding.Bindings, dispatcher frontend.Dispatcher) frontend.Frontend {
+ return windows.NewFrontend(ctx, appoptions, logger, appBindings, dispatcher)
+}
diff --git a/v2/internal/frontend/desktop/windows/browser.go b/v2/internal/frontend/desktop/windows/browser.go
new file mode 100644
index 000000000..f23b04dbe
--- /dev/null
+++ b/v2/internal/frontend/desktop/windows/browser.go
@@ -0,0 +1,14 @@
+//go:build windows
+// +build windows
+
+package windows
+
+import (
+ "github.com/pkg/browser"
+)
+
+// BrowserOpenURL Use the default browser to open the url
+func (f *Frontend) BrowserOpenURL(url string) {
+ // Specific method implementation
+ _ = browser.OpenURL(url)
+}
diff --git a/v2/internal/frontend/desktop/windows/dialog.go b/v2/internal/frontend/desktop/windows/dialog.go
new file mode 100644
index 000000000..eb7747223
--- /dev/null
+++ b/v2/internal/frontend/desktop/windows/dialog.go
@@ -0,0 +1,153 @@
+//go:build windows
+
+package windows
+
+import (
+ "github.com/leaanthony/go-common-file-dialog/cfd"
+ "github.com/wailsapp/wails/v2/internal/frontend"
+ "golang.org/x/sys/windows"
+ "syscall"
+)
+
+// OpenDirectoryDialog prompts the user to select a directory
+func (f *Frontend) OpenDirectoryDialog(options frontend.OpenDialogOptions) (string, error) {
+ config := cfd.DialogConfig{
+ Title: options.Title,
+ Role: "PickFolder",
+ Folder: options.DefaultDirectory,
+ }
+ thisDialog, err := cfd.NewSelectFolderDialog(config)
+ if err != nil {
+ return "", err
+ }
+ thisDialog.SetParentWindowHandle(f.mainWindow.Handle())
+ defer func(thisDialog cfd.SelectFolderDialog) {
+ err := thisDialog.Release()
+ if err != nil {
+ println("ERROR: Unable to release dialog:", err.Error())
+ }
+ }(thisDialog)
+ result, err := thisDialog.ShowAndGetResult()
+ if err != nil && err != cfd.ErrorCancelled {
+ return "", err
+ }
+ return result, nil
+}
+
+// OpenFileDialog prompts the user to select a file
+func (f *Frontend) OpenFileDialog(options frontend.OpenDialogOptions) (string, error) {
+ config := cfd.DialogConfig{
+ Folder: options.DefaultDirectory,
+ FileFilters: convertFilters(options.Filters),
+ FileName: options.DefaultFilename,
+ Title: options.Title,
+ }
+ thisdialog, err := cfd.NewOpenFileDialog(config)
+ if err != nil {
+ return "", err
+ }
+ thisdialog.SetParentWindowHandle(f.mainWindow.Handle())
+ defer func(thisdialog cfd.OpenFileDialog) {
+ err := thisdialog.Release()
+ if err != nil {
+ println("ERROR: Unable to release dialog:", err.Error())
+ }
+ }(thisdialog)
+ result, err := thisdialog.ShowAndGetResult()
+ if err != nil && err != cfd.ErrorCancelled {
+ return "", err
+ }
+ return result, nil
+}
+
+// OpenMultipleFilesDialog prompts the user to select a file
+func (f *Frontend) OpenMultipleFilesDialog(dialogOptions frontend.OpenDialogOptions) ([]string, error) {
+ config := cfd.DialogConfig{
+ Title: dialogOptions.Title,
+ Role: "OpenMultipleFiles",
+ FileFilters: convertFilters(dialogOptions.Filters),
+ FileName: dialogOptions.DefaultFilename,
+ Folder: dialogOptions.DefaultDirectory,
+ }
+ thisdialog, err := cfd.NewOpenMultipleFilesDialog(config)
+ if err != nil {
+ return nil, err
+ }
+ thisdialog.SetParentWindowHandle(f.mainWindow.Handle())
+ defer func(thisdialog cfd.OpenMultipleFilesDialog) {
+ err := thisdialog.Release()
+ if err != nil {
+ println("ERROR: Unable to release dialog:", err.Error())
+ }
+ }(thisdialog)
+ result, err := thisdialog.ShowAndGetResults()
+ if err != nil && err != cfd.ErrorCancelled {
+ return nil, err
+ }
+ return result, nil
+}
+
+// SaveFileDialog prompts the user to select a file
+func (f *Frontend) SaveFileDialog(dialogOptions frontend.SaveDialogOptions) (string, error) {
+ saveDialog, err := cfd.NewSaveFileDialog(cfd.DialogConfig{
+ Title: dialogOptions.Title,
+ Role: "SaveFile",
+ FileFilters: convertFilters(dialogOptions.Filters),
+ FileName: dialogOptions.DefaultFilename,
+ Folder: dialogOptions.DefaultDirectory,
+ })
+ if err != nil {
+ return "", err
+ }
+ saveDialog.SetParentWindowHandle(f.mainWindow.Handle())
+ err = saveDialog.Show()
+ if err != nil {
+ return "", err
+ }
+ result, err := saveDialog.GetResult()
+ if err != nil && err != cfd.ErrorCancelled {
+ return "", err
+ }
+ return result, nil
+}
+
+// MessageDialog show a message dialog to the user
+func (f *Frontend) MessageDialog(options frontend.MessageDialogOptions) (string, error) {
+
+ title, err := syscall.UTF16PtrFromString(options.Title)
+ if err != nil {
+ return "", err
+ }
+ message, err := syscall.UTF16PtrFromString(options.Message)
+ if err != nil {
+ return "", err
+ }
+ var flags uint32
+ switch options.Type {
+ case frontend.InfoDialog:
+ flags = windows.MB_OK | windows.MB_ICONINFORMATION
+ case frontend.ErrorDialog:
+ flags = windows.MB_ICONERROR | windows.MB_OK
+ case frontend.QuestionDialog:
+ flags = windows.MB_YESNO
+ case frontend.WarningDialog:
+ flags = windows.MB_OK | windows.MB_ICONWARNING
+ }
+
+ button, _ := windows.MessageBox(windows.HWND(f.mainWindow.Handle()), message, title, flags|windows.MB_SYSTEMMODAL)
+ // This maps MessageBox return values to strings
+ responses := []string{"", "Ok", "Cancel", "Abort", "Retry", "Ignore", "Yes", "No", "", "", "Try Again", "Continue"}
+ result := "Error"
+ if int(button) < len(responses) {
+ result = responses[button]
+ }
+ return result, nil
+}
+
+func convertFilters(filters []frontend.FileFilter) []cfd.FileFilter {
+ var result []cfd.FileFilter
+ for _, filter := range filters {
+ result = append(result, cfd.FileFilter(filter))
+ }
+ return result
+}
diff --git a/v2/internal/frontend/desktop/windows/frontend.go b/v2/internal/frontend/desktop/windows/frontend.go
new file mode 100644
index 000000000..2f551cd15
--- /dev/null
+++ b/v2/internal/frontend/desktop/windows/frontend.go
@@ -0,0 +1,431 @@
+//go:build windows
+// +build windows
+
+package windows
+
+import (
+ "context"
+ "encoding/json"
+ "fmt"
+ "log"
+ "runtime"
+ "strconv"
+ "strings"
+ "text/template"
+
+ "github.com/leaanthony/go-webview2/pkg/edge"
+ "github.com/leaanthony/winc"
+ "github.com/leaanthony/winc/w32"
+ "github.com/wailsapp/wails/v2/internal/binding"
+ "github.com/wailsapp/wails/v2/internal/frontend"
+ "github.com/wailsapp/wails/v2/internal/frontend/assetserver"
+ "github.com/wailsapp/wails/v2/internal/logger"
+ "github.com/wailsapp/wails/v2/pkg/options"
+)
+
+type Frontend struct {
+
+ // Context
+ ctx context.Context
+
+ frontendOptions *options.App
+ logger *logger.Logger
+ chromium *edge.Chromium
+ debug bool
+
+ // Assets
+ assets *assetserver.DesktopAssetServer
+ startURL string
+
+ // main window handle
+ mainWindow *Window
+ minWidth, minHeight, maxWidth, maxHeight int
+ bindings *binding.Bindings
+ dispatcher frontend.Dispatcher
+ servingFromDisk bool
+}
+
+func NewFrontend(ctx context.Context, appoptions *options.App, myLogger *logger.Logger, appBindings *binding.Bindings, dispatcher frontend.Dispatcher) *Frontend {
+
+ result := &Frontend{
+ frontendOptions: appoptions,
+ logger: myLogger,
+ bindings: appBindings,
+ dispatcher: dispatcher,
+ ctx: ctx,
+ minHeight: appoptions.MinHeight,
+ minWidth: appoptions.MinWidth,
+ maxHeight: appoptions.MaxHeight,
+ maxWidth: appoptions.MaxWidth,
+ startURL: "file://wails/",
+ }
+
+ bindingsJSON, err := appBindings.ToJSON()
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ _devServerURL := ctx.Value("devserverurl")
+ if _devServerURL != nil {
+ devServerURL := _devServerURL.(string)
+ if len(devServerURL) > 0 && devServerURL != "http://localhost:34115" {
+ result.startURL = devServerURL
+ return result
+ }
+ }
+
+ // Check if we have been given a directory to serve assets from.
+ // If so, this means we are in dev mode and are serving assets off disk.
+ // We indicate this through the `servingFromDisk` flag to ensure requests
+ // aren't cached by WebView2 in dev mode
+
+ _assetdir := ctx.Value("assetdir")
+ if _assetdir != nil {
+ result.servingFromDisk = true
+ }
+
+ assets, err := assetserver.NewDesktopAssetServer(ctx, appoptions.Assets, bindingsJSON)
+ if err != nil {
+ log.Fatal(err)
+ }
+ result.assets = assets
+
+ return result
+}
+
+func (f *Frontend) WindowReload() {
+ f.ExecJS("runtime.WindowReload();")
+}
+
+func (f *Frontend) Run(ctx context.Context) error {
+
+ f.ctx = context.WithValue(ctx, "frontend", f)
+
+ mainWindow := NewWindow(nil, f.frontendOptions)
+ f.mainWindow = mainWindow
+
+ var _debug = ctx.Value("debug")
+ if _debug != nil {
+ f.debug = _debug.(bool)
+ }
+
+ f.WindowCenter()
+ f.setupChromium()
+
+ mainWindow.OnSize().Bind(func(arg *winc.Event) {
+ f.chromium.Resize()
+ })
+
+ mainWindow.OnClose().Bind(func(arg *winc.Event) {
+ if f.frontendOptions.HideWindowOnClose {
+ f.WindowHide()
+ } else {
+ f.Quit()
+ }
+ })
+
+ go func() {
+ if f.frontendOptions.OnStartup != nil {
+ f.frontendOptions.OnStartup(f.ctx)
+ }
+ }()
+
+ if f.frontendOptions.Fullscreen {
+ mainWindow.Fullscreen()
+ }
+
+ mainWindow.Run()
+ mainWindow.Close()
+ return nil
+}
+
+func (f *Frontend) WindowCenter() {
+ runtime.LockOSThread()
+ f.mainWindow.Center()
+}
+
+func (f *Frontend) WindowSetPos(x, y int) {
+ runtime.LockOSThread()
+ f.mainWindow.SetPos(x, y)
+}
+func (f *Frontend) WindowGetPos() (int, int) {
+ runtime.LockOSThread()
+ return f.mainWindow.Pos()
+}
+
+func (f *Frontend) WindowSetSize(width, height int) {
+ runtime.LockOSThread()
+ f.mainWindow.SetSize(width, height)
+}
+
+func (f *Frontend) WindowGetSize() (int, int) {
+ runtime.LockOSThread()
+ return f.mainWindow.Size()
+}
+
+func (f *Frontend) WindowSetTitle(title string) {
+ runtime.LockOSThread()
+ f.mainWindow.SetText(title)
+}
+
+func (f *Frontend) WindowFullscreen() {
+ runtime.LockOSThread()
+ f.mainWindow.SetMaxSize(0, 0)
+ f.mainWindow.SetMinSize(0, 0)
+ f.mainWindow.Fullscreen()
+}
+
+func (f *Frontend) WindowUnFullscreen() {
+ runtime.LockOSThread()
+ f.mainWindow.UnFullscreen()
+ f.mainWindow.SetMaxSize(f.maxWidth, f.maxHeight)
+ f.mainWindow.SetMinSize(f.minWidth, f.minHeight)
+}
+
+func (f *Frontend) WindowShow() {
+ runtime.LockOSThread()
+ f.mainWindow.Show()
+}
+
+func (f *Frontend) WindowHide() {
+ runtime.LockOSThread()
+ f.mainWindow.Hide()
+}
+func (f *Frontend) WindowMaximise() {
+ runtime.LockOSThread()
+ f.mainWindow.Maximise()
+}
+func (f *Frontend) WindowUnmaximise() {
+ runtime.LockOSThread()
+ f.mainWindow.Restore()
+}
+func (f *Frontend) WindowMinimise() {
+ runtime.LockOSThread()
+ f.mainWindow.Minimise()
+}
+func (f *Frontend) WindowUnminimise() {
+ runtime.LockOSThread()
+ f.mainWindow.Restore()
+}
+
+func (f *Frontend) WindowSetMinSize(width int, height int) {
+ runtime.LockOSThread()
+ f.minWidth = width
+ f.minHeight = height
+ f.mainWindow.SetMinSize(width, height)
+}
+func (f *Frontend) WindowSetMaxSize(width int, height int) {
+ runtime.LockOSThread()
+ f.maxWidth = width
+ f.maxHeight = height
+ f.mainWindow.SetMaxSize(width, height)
+}
+
+func (f *Frontend) WindowSetRGBA(col *options.RGBA) {
+ runtime.LockOSThread()
+ if col == nil {
+ return
+ }
+
+ f.mainWindow.Dispatch(func() {
+ controller := f.chromium.GetController()
+ controller2 := controller.GetICoreWebView2Controller2()
+
+ backgroundCol := edge.COREWEBVIEW2_COLOR{
+ A: col.A,
+ R: col.R,
+ G: col.G,
+ B: col.B,
+ }
+
+ // Webview2 only has 0 and 255 as valid values.
+ if backgroundCol.A > 0 && backgroundCol.A < 255 {
+ backgroundCol.A = 255
+ }
+
+ if f.frontendOptions.Windows != nil && f.frontendOptions.Windows.WebviewIsTransparent {
+ backgroundCol.A = 0
+ }
+
+ err := controller2.PutDefaultBackgroundColor(backgroundCol)
+ if err != nil {
+ log.Fatal(err)
+ }
+ })
+}
+
+func (f *Frontend) Quit() {
+ winc.Exit()
+}
+
+func (f *Frontend) setupChromium() {
+ chromium := edge.NewChromium()
+ f.chromium = chromium
+ chromium.MessageCallback = f.processMessage
+ chromium.WebResourceRequestedCallback = f.processRequest
+ chromium.NavigationCompletedCallback = f.navigationCompleted
+ chromium.AcceleratorKeyCallback = func(vkey uint) bool {
+ w32.PostMessage(f.mainWindow.Handle(), w32.WM_KEYDOWN, uintptr(vkey), 0)
+ return false
+ }
+ chromium.Embed(f.mainWindow.Handle())
+ chromium.Resize()
+ settings, err := chromium.GetSettings()
+ if err != nil {
+ log.Fatal(err)
+ }
+ err = settings.PutAreDefaultContextMenusEnabled(f.debug)
+ if err != nil {
+ log.Fatal(err)
+ }
+ err = settings.PutAreDevToolsEnabled(f.debug)
+ if err != nil {
+ log.Fatal(err)
+ }
+ err = settings.PutIsZoomControlEnabled(false)
+ if err != nil {
+ log.Fatal(err)
+ }
+ err = settings.PutIsStatusBarEnabled(false)
+ if err != nil {
+ log.Fatal(err)
+ }
+ err = settings.PutAreBrowserAcceleratorKeysEnabled(false)
+ if err != nil {
+ log.Fatal(err)
+ }
+ err = settings.PutIsSwipeNavigationEnabled(false)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ // Set background colour
+ f.WindowSetRGBA(f.frontendOptions.RGBA)
+
+ chromium.SetGlobalPermission(edge.CoreWebView2PermissionStateAllow)
+ chromium.AddWebResourceRequestedFilter("*", edge.COREWEBVIEW2_WEB_RESOURCE_CONTEXT_ALL)
+ chromium.Navigate(f.startURL)
+}
+
+type EventNotify struct {
+ Name string `json:"name"`
+ Data []interface{} `json:"data"`
+}
+
+func (f *Frontend) Notify(name string, data ...interface{}) {
+ notification := EventNotify{
+ Name: name,
+ Data: data,
+ }
+ payload, err := json.Marshal(notification)
+ if err != nil {
+ f.logger.Error(err.Error())
+ return
+ }
+ f.ExecJS(`window.wails.EventsNotify('` + template.JSEscapeString(string(payload)) + `');`)
+}
+
+func (f *Frontend) processRequest(req *edge.ICoreWebView2WebResourceRequest, args *edge.ICoreWebView2WebResourceRequestedEventArgs) {
+ //Get the request
+ uri, _ := req.GetUri()
+
+ // Translate URI
+ uri = strings.TrimPrefix(uri, "file://wails")
+ if !strings.HasPrefix(uri, "/") {
+ return
+ }
+
+ // Load file from asset store
+ content, mimeType, err := f.assets.Load(uri)
+ if err != nil {
+ return
+ }
+
+ env := f.chromium.Environment()
+ headers := "Content-Type: " + mimeType
+ if f.servingFromDisk {
+ headers += "\nPragma: no-cache"
+ }
+ response, err := env.CreateWebResourceResponse(content, 200, "OK", headers)
+ if err != nil {
+ return
+ }
+ // Send response back
+ err = args.PutResponse(response)
+ if err != nil {
+ return
+ }
+ return
+}
+
+func (f *Frontend) processMessage(message string) {
+ if message == "drag" {
+ if !f.mainWindow.IsFullScreen() {
+ err := f.startDrag()
+ if err != nil {
+ f.logger.Error(err.Error())
+ }
+ }
+ return
+ }
+ result, err := f.dispatcher.ProcessMessage(message, f)
+ if err != nil {
+ f.logger.Error(err.Error())
+ f.Callback(result)
+ return
+ }
+ if result == "" {
+ return
+ }
+
+ switch result[0] {
+ case 'c':
+ // Callback from a method call
+ f.Callback(result[1:])
+ default:
+ f.logger.Info("Unknown message returned from dispatcher: %+v", result)
+ }
+}
+
+func (f *Frontend) Callback(message string) {
+ f.mainWindow.Dispatch(func() {
+ f.chromium.Eval(`window.wails.Callback(` + strconv.Quote(message) + `);`)
+ })
+}
+
+func (f *Frontend) startDrag() error {
+ if !w32.ReleaseCapture() {
+ return fmt.Errorf("unable to release mouse capture")
+ }
+ w32.SendMessage(f.mainWindow.Handle(), w32.WM_NCLBUTTONDOWN, w32.HTCAPTION, 0)
+ return nil
+}
+
+func (f *Frontend) ExecJS(js string) {
+ f.mainWindow.Dispatch(func() {
+ f.chromium.Eval(js)
+ })
+}
+
+func (f *Frontend) navigationCompleted(sender *edge.ICoreWebView2, args *edge.ICoreWebView2NavigationCompletedEventArgs) {
+ if f.frontendOptions.OnDomReady != nil {
+ go f.frontendOptions.OnDomReady(f.ctx)
+ }
+
+ // If you want to start hidden, return
+ if f.frontendOptions.StartHidden {
+ return
+ }
+
+ // Hack to make it visible: https://github.com/MicrosoftEdge/WebView2Feedback/issues/1077#issuecomment-825375026
+ err := f.chromium.Hide()
+ if err != nil {
+ log.Fatal(err)
+ }
+ err = f.chromium.Show()
+ if err != nil {
+ log.Fatal(err)
+ }
+ f.mainWindow.Show()
+
+}
diff --git a/v2/internal/frontend/desktop/windows/keys.go b/v2/internal/frontend/desktop/windows/keys.go
new file mode 100644
index 000000000..8c2c39bde
--- /dev/null
+++ b/v2/internal/frontend/desktop/windows/keys.go
@@ -0,0 +1,202 @@
+//go:build windows
+
+package windows
+
+import (
+ "github.com/leaanthony/winc"
+ "github.com/wailsapp/wails/v2/pkg/menu/keys"
+ "strings"
+)
+
+var ModifierMap = map[keys.Modifier]winc.Modifiers{
+ keys.ShiftKey: winc.ModShift,
+ keys.ControlKey: winc.ModControl,
+ keys.OptionOrAltKey: winc.ModAlt,
+ keys.CmdOrCtrlKey: winc.ModControl,
+}
+
+func acceleratorToWincShortcut(accelerator *keys.Accelerator) winc.Shortcut {
+
+ if accelerator == nil {
+ return winc.NoShortcut
+ }
+ inKey := strings.ToUpper(accelerator.Key)
+ key, exists := keyMap[inKey]
+ if !exists {
+ return winc.NoShortcut
+ }
+ var modifiers winc.Modifiers
+ if _, exists := shiftMap[inKey]; exists {
+ modifiers = winc.ModShift
+ }
+ for _, mod := range accelerator.Modifiers {
+ modifiers |= ModifierMap[mod]
+ }
+ return winc.Shortcut{
+ Modifiers: modifiers,
+ Key: key,
+ }
+}
+
+var shiftMap = map[string]struct{}{
+ "~": {},
+ ")": {},
+ "!": {},
+ "@": {},
+ "#": {},
+ "$": {},
+ "%": {},
+ "^": {},
+ "&": {},
+ "*": {},
+ "(": {},
+ "_": {},
+ "PLUS": {},
+ "<": {},
+ ">": {},
+ "?": {},
+ ":": {},
+ `"`: {},
+ "{": {},
+ "}": {},
+ "|": {},
+}
+
+var keyMap = map[string]winc.Key{
+ "0": winc.Key0,
+ "1": winc.Key1,
+ "2": winc.Key2,
+ "3": winc.Key3,
+ "4": winc.Key4,
+ "5": winc.Key5,
+ "6": winc.Key6,
+ "7": winc.Key7,
+ "8": winc.Key8,
+ "9": winc.Key9,
+ "A": winc.KeyA,
+ "B": winc.KeyB,
+ "C": winc.KeyC,
+ "D": winc.KeyD,
+ "E": winc.KeyE,
+ "F": winc.KeyF,
+ "G": winc.KeyG,
+ "H": winc.KeyH,
+ "I": winc.KeyI,
+ "J": winc.KeyJ,
+ "K": winc.KeyK,
+ "L": winc.KeyL,
+ "M": winc.KeyM,
+ "N": winc.KeyN,
+ "O": winc.KeyO,
+ "P": winc.KeyP,
+ "Q": winc.KeyQ,
+ "R": winc.KeyR,
+ "S": winc.KeyS,
+ "T": winc.KeyT,
+ "U": winc.KeyU,
+ "V": winc.KeyV,
+ "W": winc.KeyW,
+ "X": winc.KeyX,
+ "Y": winc.KeyY,
+ "Z": winc.KeyZ,
+ "F1": winc.KeyF1,
+ "F2": winc.KeyF2,
+ "F3": winc.KeyF3,
+ "F4": winc.KeyF4,
+ "F5": winc.KeyF5,
+ "F6": winc.KeyF6,
+ "F7": winc.KeyF7,
+ "F8": winc.KeyF8,
+ "F9": winc.KeyF9,
+ "F10": winc.KeyF10,
+ "F11": winc.KeyF11,
+ "F12": winc.KeyF12,
+ "F13": winc.KeyF13,
+ "F14": winc.KeyF14,
+ "F15": winc.KeyF15,
+ "F16": winc.KeyF16,
+ "F17": winc.KeyF17,
+ "F18": winc.KeyF18,
+ "F19": winc.KeyF19,
+ "F20": winc.KeyF20,
+ "F21": winc.KeyF21,
+ "F22": winc.KeyF22,
+ "F23": winc.KeyF23,
+ "F24": winc.KeyF24,
+
+ "`": winc.KeyOEM3,
+ ",": winc.KeyOEMComma,
+ ".": winc.KeyOEMPeriod,
+ "/": winc.KeyOEM2,
+ ";": winc.KeyOEM1,
+ "'": winc.KeyOEM7,
+ "[": winc.KeyOEM4,
+ "]": winc.KeyOEM6,
+ `\`: winc.KeyOEM5,
+
+ "~": winc.KeyOEM3, //
+ ")": winc.Key0,
+ "!": winc.Key1,
+ "@": winc.Key2,
+ "#": winc.Key3,
+ "$": winc.Key4,
+ "%": winc.Key5,
+ "^": winc.Key6,
+ "&": winc.Key7,
+ "*": winc.Key8,
+ "(": winc.Key9,
+ "_": winc.KeyOEMMinus,
+ "PLUS": winc.KeyOEMPlus,
+ "<": winc.KeyOEMComma,
+ ">": winc.KeyOEMPeriod,
+ "?": winc.KeyOEM2,
+ ":": winc.KeyOEM1,
+ `"`: winc.KeyOEM7,
+ "{": winc.KeyOEM4,
+ "}": winc.KeyOEM6,
+ "|": winc.KeyOEM5,
+
+ "SPACE": winc.KeySpace,
+ "TAB": winc.KeyTab,
+ "CAPSLOCK": winc.KeyCapital,
+ "NUMLOCK": winc.KeyNumlock,
+ "SCROLLLOCK": winc.KeyScroll,
+ "BACKSPACE": winc.KeyBack,
+ "DELETE": winc.KeyDelete,
+ "INSERT": winc.KeyInsert,
+ "RETURN": winc.KeyReturn,
+ "ENTER": winc.KeyReturn,
+ "UP": winc.KeyUp,
+ "DOWN": winc.KeyDown,
+ "LEFT": winc.KeyLeft,
+ "RIGHT": winc.KeyRight,
+ "HOME": winc.KeyHome,
+ "END": winc.KeyEnd,
+ "PAGEUP": winc.KeyPrior,
+ "PAGEDOWN": winc.KeyNext,
+ "ESCAPE": winc.KeyEscape,
+ "ESC": winc.KeyEscape,
+ "VOLUMEUP": winc.KeyVolumeUp,
+ "VOLUMEDOWN": winc.KeyVolumeDown,
+ "VOLUMEMUTE": winc.KeyVolumeMute,
+ "MEDIANEXTTRACK": winc.KeyMediaNextTrack,
+ "MEDIAPREVIOUSTRACK": winc.KeyMediaPrevTrack,
+ "MEDIASTOP": winc.KeyMediaStop,
+ "MEDIAPLAYPAUSE": winc.KeyMediaPlayPause,
+ "PRINTSCREEN": winc.KeyPrint,
+ "NUM0": winc.KeyNumpad0,
+ "NUM1": winc.KeyNumpad1,
+ "NUM2": winc.KeyNumpad2,
+ "NUM3": winc.KeyNumpad3,
+ "NUM4": winc.KeyNumpad4,
+ "NUM5": winc.KeyNumpad5,
+ "NUM6": winc.KeyNumpad6,
+ "NUM7": winc.KeyNumpad7,
+ "NUM8": winc.KeyNumpad8,
+ "NUM9": winc.KeyNumpad9,
+ "nummult": winc.KeyMultiply,
+ "numadd": winc.KeyAdd,
+ "numsub": winc.KeySubtract,
+ "numdec": winc.KeyDecimal,
+ "numdiv": winc.KeyDivide,
+}
diff --git a/v2/internal/frontend/desktop/windows/menu.go b/v2/internal/frontend/desktop/windows/menu.go
new file mode 100644
index 000000000..82f5421ed
--- /dev/null
+++ b/v2/internal/frontend/desktop/windows/menu.go
@@ -0,0 +1,129 @@
+//go:build windows
+
+package windows
+
+import (
+ "github.com/leaanthony/winc"
+ "github.com/wailsapp/wails/v2/pkg/menu"
+)
+
+var checkboxMap = map[*menu.MenuItem][]*winc.MenuItem{}
+var radioGroupMap = map[*menu.MenuItem][]*winc.MenuItem{}
+
+func toggleCheckBox(menuItem *menu.MenuItem) {
+ menuItem.Checked = !menuItem.Checked
+ for _, wincMenu := range checkboxMap[menuItem] {
+ wincMenu.SetChecked(menuItem.Checked)
+ }
+}
+
+func addCheckBoxToMap(menuItem *menu.MenuItem, wincMenuItem *winc.MenuItem) {
+ if checkboxMap[menuItem] == nil {
+ checkboxMap[menuItem] = []*winc.MenuItem{}
+ }
+ checkboxMap[menuItem] = append(checkboxMap[menuItem], wincMenuItem)
+}
+
+func toggleRadioItem(menuItem *menu.MenuItem) {
+ menuItem.Checked = !menuItem.Checked
+ for _, wincMenu := range radioGroupMap[menuItem] {
+ wincMenu.SetChecked(menuItem.Checked)
+ }
+}
+
+func addRadioItemToMap(menuItem *menu.MenuItem, wincMenuItem *winc.MenuItem) {
+ if radioGroupMap[menuItem] == nil {
+ radioGroupMap[menuItem] = []*winc.MenuItem{}
+ }
+ radioGroupMap[menuItem] = append(radioGroupMap[menuItem], wincMenuItem)
+}
+
+func (w *Window) SetApplicationMenu(menu *menu.Menu) {
+ w.applicationMenu = menu
+ processMenu(w, menu)
+}
+
+func processMenu(window *Window, menu *menu.Menu) {
+ mainMenu := window.NewMenu()
+ for _, menuItem := range menu.Items {
+ submenu := mainMenu.AddSubMenu(menuItem.Label)
+ for _, menuItem := range menuItem.SubMenu.Items {
+ processMenuItem(submenu, menuItem)
+ }
+ }
+ mainMenu.Show()
+}
+
+func processMenuItem(parent *winc.MenuItem, menuItem *menu.MenuItem) {
+ if menuItem.Hidden {
+ return
+ }
+ switch menuItem.Type {
+ case menu.SeparatorType:
+ parent.AddSeparator()
+ case menu.TextType:
+ shortcut := acceleratorToWincShortcut(menuItem.Accelerator)
+ newItem := parent.AddItem(menuItem.Label, shortcut)
+ //if menuItem.Tooltip != "" {
+ // newItem.SetToolTip(menuItem.Tooltip)
+ //}
+ if menuItem.Click != nil {
+ newItem.OnClick().Bind(func(e *winc.Event) {
+ menuItem.Click(&menu.CallbackData{
+ MenuItem: menuItem,
+ })
+ })
+ }
+ newItem.SetEnabled(!menuItem.Disabled)
+
+ case menu.CheckboxType:
+ shortcut := acceleratorToWincShortcut(menuItem.Accelerator)
+ newItem := parent.AddItem(menuItem.Label, shortcut)
+ newItem.SetCheckable(true)
+ newItem.SetChecked(menuItem.Checked)
+ //if menuItem.Tooltip != "" {
+ // newItem.SetToolTip(menuItem.Tooltip)
+ //}
+ if menuItem.Click != nil {
+ newItem.OnClick().Bind(func(e *winc.Event) {
+ toggleCheckBox(menuItem)
+ menuItem.Click(&menu.CallbackData{
+ MenuItem: menuItem,
+ })
+ })
+ }
+ newItem.SetEnabled(!menuItem.Disabled)
+ addCheckBoxToMap(menuItem, newItem)
+ case menu.RadioType:
+ shortcut := acceleratorToWincShortcut(menuItem.Accelerator)
+ newItem := parent.AddItemRadio(menuItem.Label, shortcut)
+ newItem.SetCheckable(true)
+ newItem.SetChecked(menuItem.Checked)
+ //if menuItem.Tooltip != "" {
+ // newItem.SetToolTip(menuItem.Tooltip)
+ //}
+ if menuItem.Click != nil {
+ newItem.OnClick().Bind(func(e *winc.Event) {
+ toggleRadioItem(menuItem)
+ menuItem.Click(&menu.CallbackData{
+ MenuItem: menuItem,
+ })
+ })
+ }
+ newItem.SetEnabled(!menuItem.Disabled)
+ addRadioItemToMap(menuItem, newItem)
+ case menu.SubmenuType:
+ submenu := parent.AddSubMenu(menuItem.Label)
+ for _, menuItem := range menuItem.SubMenu.Items {
+ processMenuItem(submenu, menuItem)
+ }
+ }
+}
+
+func (f *Frontend) MenuSetApplicationMenu(menu *menu.Menu) {
+ f.mainWindow.SetApplicationMenu(menu)
+}
+
+func (f *Frontend) MenuUpdateApplicationMenu() {
+ processMenu(f.mainWindow, f.mainWindow.applicationMenu)
+}
diff --git a/v2/internal/frontend/desktop/windows/window.go b/v2/internal/frontend/desktop/windows/window.go
new file mode 100644
index 000000000..8087e37fa
--- /dev/null
+++ b/v2/internal/frontend/desktop/windows/window.go
@@ -0,0 +1,117 @@
+//go:build windows
+
+package windows
+
+import (
+ "github.com/leaanthony/winc"
+ "github.com/leaanthony/winc/w32"
+ "github.com/wailsapp/wails/v2/pkg/menu"
+ "github.com/wailsapp/wails/v2/pkg/options"
+ "sync"
+)
+
+type Window struct {
+ winc.Form
+ frontendOptions *options.App
+ applicationMenu *menu.Menu
+ m sync.Mutex
+ dispatchq []func()
+}
+
+func NewWindow(parent winc.Controller, options *options.App) *Window {
+ result := new(Window)
+ result.frontendOptions = options
+ result.SetIsForm(true)
+
+ var exStyle int
+ if options.Windows != nil {
+ exStyle = w32.WS_EX_CONTROLPARENT | w32.WS_EX_APPWINDOW
+ if options.Windows.WindowIsTranslucent {
+ exStyle |= w32.WS_EX_NOREDIRECTIONBITMAP
+ }
+ }
+ if options.AlwaysOnTop {
+ exStyle |= w32.WS_EX_TOPMOST
+ }
+
+ var dwStyle = w32.WS_OVERLAPPEDWINDOW
+ if options.Frameless {
+ dwStyle = w32.WS_POPUP
+ }
+
+ winc.RegClassOnlyOnce("wailsWindow")
+ result.SetHandle(winc.CreateWindow("wailsWindow", parent, uint(exStyle), uint(dwStyle)))
+ result.SetParent(parent)
+
+ loadIcon := true
+ if options.Windows != nil && options.Windows.DisableWindowIcon == true {
+ loadIcon = false
+ }
+ if loadIcon {
+ if ico, err := winc.NewIconFromResource(winc.GetAppInstance(), uint16(winc.AppIconID)); err == nil {
+ result.SetIcon(0, ico)
+ }
+ }
+
+ result.SetSize(options.Width, options.Height)
+ result.SetText(options.Title)
+ if options.Frameless == false && !options.Fullscreen {
+ result.EnableMaxButton(!options.DisableResize)
+ result.EnableSizable(!options.DisableResize)
+ result.SetMinSize(options.MinWidth, options.MinHeight)
+ result.SetMaxSize(options.MaxWidth, options.MaxHeight)
+ }
+
+ if options.Windows != nil {
+ if options.Windows.WindowIsTranslucent {
+ result.SetTranslucentBackground()
+ }
+
+ if options.Windows.DisableWindowIcon {
+ result.DisableIcon()
+ }
+ }
+
+ // Dlg forces display of focus rectangles, as soon as the user starts to type.
+ w32.SendMessage(result.Handle(), w32.WM_CHANGEUISTATE, w32.UIS_INITIALIZE, 0)
+ winc.RegMsgHandler(result)
+
+ result.SetFont(winc.DefaultFont)
+
+ if options.Menu != nil {
+ result.SetApplicationMenu(options.Menu)
+ }
+
+ return result
+}
+
+func (w *Window) Run() int {
+ var m w32.MSG
+
+ for w32.GetMessage(&m, 0, 0, 0) != 0 {
+ if m.Message == w32.WM_APP {
+ // Credit: https://github.com/jchv/go-webview2
+ w.m.Lock()
+ q := append([]func(){}, w.dispatchq...)
+ w.dispatchq = []func(){}
+ w.m.Unlock()
+ for _, v := range q {
+ v()
+ }
+ }
+ if !w.PreTranslateMessage(&m) {
+ w32.TranslateMessage(&m)
+ w32.DispatchMessage(&m)
+ }
+ }
+
+ w32.GdiplusShutdown()
+ return int(m.WParam)
+}
+
+func (w *Window) Dispatch(f func()) {
+ w.m.Lock()
+ w.dispatchq = append(w.dispatchq, f)
+ w.m.Unlock()
+ w32.PostMainThreadMessage(w32.WM_APP, 0, 0)
+}
diff --git a/v2/internal/frontend/devserver/devserver.go b/v2/internal/frontend/devserver/devserver.go
new file mode 100644
index 000000000..e73828c5d
--- /dev/null
+++ b/v2/internal/frontend/devserver/devserver.go
@@ -0,0 +1,394 @@
+//go:build dev
+
+// Package devserver provides a web-based frontend so that
+// it is possible to run a Wails app in a browsers.
+package devserver
+
+import (
+ "context"
+ "encoding/json"
+ "fmt"
+ "io/fs"
+ "log"
+ "path/filepath"
+ "strings"
+ "sync"
+ "time"
+
+ "github.com/gofiber/fiber/v2"
+ "github.com/gofiber/websocket/v2"
+ "github.com/wailsapp/wails/v2/internal/binding"
+ "github.com/wailsapp/wails/v2/internal/frontend"
+ "github.com/wailsapp/wails/v2/internal/frontend/assetserver"
+ "github.com/wailsapp/wails/v2/internal/logger"
+ "github.com/wailsapp/wails/v2/internal/menumanager"
+ "github.com/wailsapp/wails/v2/pkg/menu"
+ "github.com/wailsapp/wails/v2/pkg/options"
+)
+
+type DevWebServer struct {
+ server *fiber.App
+ ctx context.Context
+ appoptions *options.App
+ logger *logger.Logger
+ appBindings *binding.Bindings
+ dispatcher frontend.Dispatcher
+ assetServer *assetserver.BrowserAssetServer
+ socketMutex sync.Mutex
+ websocketClients map[*websocket.Conn]*sync.Mutex
+ menuManager *menumanager.Manager
+ starttime string
+
+ // Desktop frontend
+ desktopFrontend frontend.Frontend
+}
+
+func (d *DevWebServer) WindowReload() {
+ d.broadcast("reload")
+}
+
+func (d *DevWebServer) Run(ctx context.Context) error {
+ d.ctx = ctx
+
+ d.server.Get("/wails/reload", func(fctx *fiber.Ctx) error {
+ d.WindowReload()
+ d.desktopFrontend.WindowReload()
+ return nil
+ })
+
+ d.server.Get("/wails/ipc", websocket.New(func(c *websocket.Conn) {
+ d.newWebsocketSession(c)
+ locker := d.websocketClients[c]
+ // websocket.Conn bindings https://pkg.go.dev/github.com/fasthttp/websocket?tab=doc#pkg-index
+ var (
+ mt int
+ msg []byte
+ err error
+ )
+
+ for {
+ if mt, msg, err = c.ReadMessage(); err != nil {
+ break
+ }
+ // We do not support drag in browsers
+ if string(msg) == "drag" {
+ continue
+ }
+
+ // Notify the other browsers of "EventEmit"
+ if len(msg) > 2 && strings.HasPrefix(string(msg), "EE") {
+ d.notifyExcludingSender(msg, c)
+ }
+
+ // Send the message to dispatch to the frontend
+ result, err := d.dispatcher.ProcessMessage(string(msg), d)
+ if err != nil {
+ d.logger.Error(err.Error())
+ }
+ if result != "" {
+ locker.Lock()
+ if err = c.WriteMessage(mt, []byte(result)); err != nil {
+ locker.Unlock()
+ break
+ }
+ locker.Unlock()
+ }
+
+ }
+ }))
+
+ _devServerURL := ctx.Value("devserverurl")
+ if _devServerURL == "http://localhost:34115" {
+ // Setup internal dev server
+ _assetdir := ctx.Value("assetdir")
+ if _assetdir == nil {
+ return fmt.Errorf("no assetdir provided")
+ }
+ if _assetdir != nil {
+ assetdir := _assetdir.(string)
+ bindingsJSON, err := d.appBindings.ToJSON()
+ if err != nil {
+ log.Fatal(err)
+ }
+ d.assetServer, err = assetserver.NewBrowserAssetServer(assetdir, bindingsJSON, d.appoptions)
+ if err != nil {
+ log.Fatal(err)
+ }
+ absdir, err := filepath.Abs(assetdir)
+ if err != nil {
+ return err
+ }
+ d.LogDebug("Serving assets from: %s", absdir)
+ }
+
+ d.server.Get("*", d.loadAsset)
+
+ // Start server
+ go func(server *fiber.App, log *logger.Logger) {
+ err := server.Listen("localhost:34115")
+ if err != nil {
+ log.Error(err.Error())
+ }
+ d.LogDebug("Shutdown completed")
+ }(d.server, d.logger)
+
+ d.LogDebug("Serving application at http://localhost:34115")
+
+ defer func() {
+ err := d.server.Shutdown()
+ if err != nil {
+ d.logger.Error(err.Error())
+ }
+ }()
+ }
+
+ // Launch desktop app
+ err := d.desktopFrontend.Run(ctx)
+ d.LogDebug("Starting shutdown")
+
+ return err
+}
+
+func (d *DevWebServer) Quit() {
+ d.desktopFrontend.Quit()
+}
+
+func (d *DevWebServer) OpenFileDialog(dialogOptions frontend.OpenDialogOptions) (string, error) {
+ return d.desktopFrontend.OpenFileDialog(dialogOptions)
+}
+
+func (d *DevWebServer) OpenMultipleFilesDialog(dialogOptions frontend.OpenDialogOptions) ([]string, error) {
+ return d.OpenMultipleFilesDialog(dialogOptions)
+}
+
+func (d *DevWebServer) OpenDirectoryDialog(dialogOptions frontend.OpenDialogOptions) (string, error) {
+ return d.OpenDirectoryDialog(dialogOptions)
+}
+
+func (d *DevWebServer) SaveFileDialog(dialogOptions frontend.SaveDialogOptions) (string, error) {
+ return d.desktopFrontend.SaveFileDialog(dialogOptions)
+}
+
+func (d *DevWebServer) MessageDialog(dialogOptions frontend.MessageDialogOptions) (string, error) {
+ return d.desktopFrontend.MessageDialog(dialogOptions)
+}
+
+func (d *DevWebServer) WindowSetTitle(title string) {
+ d.desktopFrontend.WindowSetTitle(title)
+}
+
+func (d *DevWebServer) WindowShow() {
+ d.desktopFrontend.WindowShow()
+}
+
+func (d *DevWebServer) WindowHide() {
+ d.desktopFrontend.WindowHide()
+}
+
+func (d *DevWebServer) WindowCenter() {
+ d.desktopFrontend.WindowCenter()
+}
+
+func (d *DevWebServer) WindowMaximise() {
+ d.desktopFrontend.WindowMaximise()
+}
+
+func (d *DevWebServer) WindowUnmaximise() {
+ d.desktopFrontend.WindowUnmaximise()
+}
+
+func (d *DevWebServer) WindowMinimise() {
+ d.desktopFrontend.WindowMinimise()
+}
+
+func (d *DevWebServer) WindowUnminimise() {
+ d.desktopFrontend.WindowUnminimise()
+}
+
+func (d *DevWebServer) WindowSetPos(x int, y int) {
+ d.desktopFrontend.WindowSetPos(x, y)
+}
+
+func (d *DevWebServer) WindowGetPos() (int, int) {
+ return d.desktopFrontend.WindowGetPos()
+}
+
+func (d *DevWebServer) WindowSetSize(width int, height int) {
+ d.desktopFrontend.WindowSetSize(width, height)
+}
+
+func (d *DevWebServer) WindowGetSize() (int, int) {
+ return d.desktopFrontend.WindowGetSize()
+}
+
+func (d *DevWebServer) WindowSetMinSize(width int, height int) {
+ d.desktopFrontend.WindowSetMinSize(width, height)
+}
+
+func (d *DevWebServer) WindowSetMaxSize(width int, height int) {
+ d.desktopFrontend.WindowSetMaxSize(width, height)
+}
+
+func (d *DevWebServer) WindowFullscreen() {
+ d.desktopFrontend.WindowFullscreen()
+}
+
+func (d *DevWebServer) WindowUnFullscreen() {
+ d.desktopFrontend.WindowUnFullscreen()
+}
+
+func (d *DevWebServer) WindowSetRGBA(col *options.RGBA) {
+ d.desktopFrontend.WindowSetRGBA(col)
+}
+
+func (d *DevWebServer) MenuSetApplicationMenu(menu *menu.Menu) {
+ d.desktopFrontend.MenuSetApplicationMenu(menu)
+}
+
+func (d *DevWebServer) MenuUpdateApplicationMenu() {
+ d.desktopFrontend.MenuUpdateApplicationMenu()
+}
+
+// BrowserOpenURL uses the system default browser to open the url
+func (d *DevWebServer) BrowserOpenURL(url string) {
+ d.desktopFrontend.BrowserOpenURL(url)
+}
+
+func (d *DevWebServer) Notify(name string, data ...interface{}) {
+ d.notify(name, data...)
+}
+
+func (d *DevWebServer) loadAsset(ctx *fiber.Ctx) error {
+ data, mimetype, err := d.assetServer.Load(ctx.Path())
+ if err != nil {
+ _, ok := err.(*fs.PathError)
+ if !ok {
+ return err
+ }
+ err := ctx.SendStatus(404)
+ if err != nil {
+ return err
+ }
+ return nil
+ }
+ err = ctx.SendStatus(200)
+ if err != nil {
+ return err
+ }
+ ctx.Set("Content-Type", mimetype)
+ err = ctx.Send(data)
+ if err != nil {
+ return err
+ }
+ return nil
+}
+
+func (d *DevWebServer) LogDebug(message string, args ...interface{}) {
+ d.logger.Debug("[DevWebServer] "+message, args...)
+}
+
+func (d *DevWebServer) newWebsocketSession(c *websocket.Conn) {
+ d.socketMutex.Lock()
+ defer d.socketMutex.Unlock()
+ c.SetCloseHandler(func(code int, text string) error {
+ d.socketMutex.Lock()
+ defer d.socketMutex.Unlock()
+ delete(d.websocketClients, c)
+ d.LogDebug(fmt.Sprintf("Websocket client %p disconnected", c))
+ return nil
+ })
+ d.websocketClients[c] = &sync.Mutex{}
+ d.LogDebug(fmt.Sprintf("Websocket client %p connected", c))
+}
+
+type EventNotify struct {
+ Name string `json:"name"`
+ Data []interface{} `json:"data"`
+}
+
+func (d *DevWebServer) broadcast(message string) {
+ d.socketMutex.Lock()
+ defer d.socketMutex.Unlock()
+ for client, locker := range d.websocketClients {
+ go func() {
+ if client == nil {
+ d.logger.Error("Lost connection to websocket server")
+ return
+ }
+ locker.Lock()
+ err := client.WriteMessage(websocket.TextMessage, []byte(message))
+ if err != nil {
+ locker.Unlock()
+ d.logger.Error(err.Error())
+ return
+ }
+ locker.Unlock()
+ }()
+ }
+}
+
+func (d *DevWebServer) notify(name string, data ...interface{}) {
+ // Notify
+ notification := EventNotify{
+ Name: name,
+ Data: data,
+ }
+ payload, err := json.Marshal(notification)
+ if err != nil {
+ d.logger.Error(err.Error())
+ return
+ }
+ d.broadcast("n" + string(payload))
+}
+
+func (d *DevWebServer) broadcastExcludingSender(message string, sender *websocket.Conn) {
+ d.socketMutex.Lock()
+ defer d.socketMutex.Unlock()
+ for client, locker := range d.websocketClients {
+ go func() {
+ if client == sender {
+ return
+ }
+ locker.Lock()
+ err := client.WriteMessage(websocket.TextMessage, []byte(message))
+ if err != nil {
+ locker.Unlock()
+ d.logger.Error(err.Error())
+ return
+ }
+ locker.Unlock()
+ }()
+ }
+}
+
+func (d *DevWebServer) notifyExcludingSender(eventMessage []byte, sender *websocket.Conn) {
+ message := "n" + string(eventMessage[2:])
+ d.broadcastExcludingSender(message, sender)
+
+ var notifyMessage EventNotify
+ err := json.Unmarshal(eventMessage[2:], ¬ifyMessage)
+ if err != nil {
+ d.logger.Error(err.Error())
+ return
+ }
+ d.desktopFrontend.Notify(notifyMessage.Name, notifyMessage.Data...)
+}
+
+func NewFrontend(ctx context.Context, appoptions *options.App, myLogger *logger.Logger, appBindings *binding.Bindings, dispatcher frontend.Dispatcher, menuManager *menumanager.Manager, desktopFrontend frontend.Frontend) *DevWebServer {
+ result := &DevWebServer{
+ ctx: ctx,
+ desktopFrontend: desktopFrontend,
+ appoptions: appoptions,
+ logger: myLogger,
+ appBindings: appBindings,
+ dispatcher: dispatcher,
+ server: fiber.New(fiber.Config{
+
+ ReadTimeout: time.Second * 5,
+ DisableStartupMessage: true,
+ }),
+ menuManager: menuManager,
+ websocketClients: make(map[*websocket.Conn]*sync.Mutex),
+ }
+ return result
+}
diff --git a/v2/internal/frontend/dispatcher.go b/v2/internal/frontend/dispatcher.go
new file mode 100644
index 000000000..367f4cdc8
--- /dev/null
+++ b/v2/internal/frontend/dispatcher.go
@@ -0,0 +1,5 @@
+package frontend
+
+type Dispatcher interface {
+ ProcessMessage(message string, sender Frontend) (string, error)
+}
diff --git a/v2/internal/frontend/dispatcher/browser.go b/v2/internal/frontend/dispatcher/browser.go
new file mode 100644
index 000000000..9ff02e8d3
--- /dev/null
+++ b/v2/internal/frontend/dispatcher/browser.go
@@ -0,0 +1,23 @@
+package dispatcher
+
+import (
+ "errors"
+
+ "github.com/wailsapp/wails/v2/internal/frontend"
+)
+
+// processBrowserMessage processing browser messages
+func (d *Dispatcher) processBrowserMessage(message string, sender frontend.Frontend) (string, error) {
+ if len(message) < 2 {
+ return "", errors.New("Invalid Browser Message: " + message)
+ }
+ switch message[1] {
+ case 'O':
+ url := message[3:]
+ go sender.BrowserOpenURL(url)
+ default:
+ d.log.Error("unknown Browser message: %s", message)
+ }
+
+ return "", nil
+}
diff --git a/v2/internal/frontend/dispatcher/calls.go b/v2/internal/frontend/dispatcher/calls.go
new file mode 100644
index 000000000..ef19c6030
--- /dev/null
+++ b/v2/internal/frontend/dispatcher/calls.go
@@ -0,0 +1,81 @@
+package dispatcher
+
+import (
+ "encoding/json"
+ "fmt"
+ "github.com/wailsapp/wails/v2/internal/frontend"
+ "strings"
+)
+
+type callMessage struct {
+ Name string `json:"name"`
+ Args []json.RawMessage `json:"args"`
+ CallbackID string `json:"callbackID"`
+}
+
+func (d *Dispatcher) processCallMessage(message string, sender frontend.Frontend) (string, error) {
+
+ var payload callMessage
+ err := json.Unmarshal([]byte(message[1:]), &payload)
+ if err != nil {
+ return "", err
+ }
+
+ var result interface{}
+
+ // Handle different calls
+ switch true {
+ case strings.HasPrefix(payload.Name, systemCallPrefix):
+ result, err = d.processSystemCall(payload, sender)
+ default:
+ // Lookup method
+ registeredMethod := d.bindingsDB.GetMethod(payload.Name)
+
+ // Check we have it
+ if registeredMethod == nil {
+ return "", fmt.Errorf("method '%s' not registered", payload.Name)
+ }
+
+ args, err2 := registeredMethod.ParseArgs(payload.Args)
+ if err2 != nil {
+ errmsg := fmt.Errorf("error parsing arguments: %s", err2.Error())
+ result, _ := d.NewErrorCallback(errmsg.Error(), payload.CallbackID)
+ return result, errmsg
+ }
+ result, err = registeredMethod.Call(args)
+ }
+
+ callbackMessage := &CallbackMessage{
+ CallbackID: payload.CallbackID,
+ }
+ if err != nil {
+ callbackMessage.Err = err.Error()
+ } else {
+ callbackMessage.Result = result
+ }
+ messageData, err := json.Marshal(callbackMessage)
+ d.log.Trace("json call result data: %+v\n", string(messageData))
+ if err != nil {
+ // what now?
+ d.log.Fatal(err.Error())
+ }
+
+ return "c" + string(messageData), nil
+}
+
+// CallbackMessage defines a message that contains the result of a call
+type CallbackMessage struct {
+ Result interface{} `json:"result"`
+ Err string `json:"error"`
+ CallbackID string `json:"callbackid"`
+}
+
+func (d *Dispatcher) NewErrorCallback(message string, callbackID string) (string, error) {
+ result := &CallbackMessage{
+ CallbackID: callbackID,
+ Err: message,
+ }
+ messageData, err := json.Marshal(result)
+ d.log.Trace("json call result data: %+v\n", string(messageData))
+ return string(messageData), err
+}
diff --git a/v2/internal/frontend/dispatcher/dispatcher.go b/v2/internal/frontend/dispatcher/dispatcher.go
new file mode 100644
index 000000000..a3091f41c
--- /dev/null
+++ b/v2/internal/frontend/dispatcher/dispatcher.go
@@ -0,0 +1,47 @@
+package dispatcher
+
+import (
+ "github.com/pkg/errors"
+ "github.com/wailsapp/wails/v2/internal/binding"
+ "github.com/wailsapp/wails/v2/internal/frontend"
+ "github.com/wailsapp/wails/v2/internal/logger"
+)
+
+type Dispatcher struct {
+ log *logger.Logger
+ bindings *binding.Bindings
+ events frontend.Events
+ bindingsDB *binding.DB
+}
+
+func NewDispatcher(log *logger.Logger, bindings *binding.Bindings, events frontend.Events) *Dispatcher {
+ return &Dispatcher{
+ log: log,
+ bindings: bindings,
+ events: events,
+ bindingsDB: bindings.DB(),
+ }
+}
+
+func (d *Dispatcher) ProcessMessage(message string, sender frontend.Frontend) (string, error) {
+ if message == "" {
+ return "", errors.New("No message to process")
+ }
+ switch message[0] {
+ case 'L':
+ return d.processLogMessage(message)
+ case 'E':
+ return d.processEventMessage(message, sender)
+ case 'C':
+ return d.processCallMessage(message, sender)
+ case 'W':
+ return d.processWindowMessage(message, sender)
+ case 'B':
+ return d.processBrowserMessage(message, sender)
+ case 'Q':
+ sender.Quit()
+ return "", nil
+ default:
+ return "", errors.New("Unknown message from front end: " + message)
+ }
+}
diff --git a/v2/internal/frontend/dispatcher/events.go b/v2/internal/frontend/dispatcher/events.go
new file mode 100644
index 000000000..cb308b803
--- /dev/null
+++ b/v2/internal/frontend/dispatcher/events.go
@@ -0,0 +1,33 @@
+package dispatcher
+
+import (
+ "encoding/json"
+ "errors"
+ "github.com/wailsapp/wails/v2/internal/frontend"
+)
+
+type EventMessage struct {
+ Name string `json:"name"`
+ Data []interface{} `json:"data"`
+}
+
+func (d *Dispatcher) processEventMessage(message string, sender frontend.Frontend) (string, error) {
+ if len(message) < 3 {
+ return "", errors.New("Invalid Event Message: " + message)
+ }
+
+ switch message[1] {
+ case 'E':
+ var eventMessage EventMessage
+ err := json.Unmarshal([]byte(message[2:]), &eventMessage)
+ if err != nil {
+ return "", err
+ }
+ go d.events.Notify(sender, eventMessage.Name, eventMessage.Data)
+ case 'X':
+ eventName := message[2:]
+ go d.events.Off(eventName)
+ }
+
+ return "", nil
+}
diff --git a/v2/internal/frontend/dispatcher/log.go b/v2/internal/frontend/dispatcher/log.go
new file mode 100644
index 000000000..e42555397
--- /dev/null
+++ b/v2/internal/frontend/dispatcher/log.go
@@ -0,0 +1,49 @@
+package dispatcher
+
+import (
+ "github.com/pkg/errors"
+ "github.com/wailsapp/wails/v2/internal/logger"
+ pkgLogger "github.com/wailsapp/wails/v2/pkg/logger"
+)
+
+var logLevelMap = map[byte]logger.LogLevel{
+ '1': pkgLogger.TRACE,
+ '2': pkgLogger.DEBUG,
+ '3': pkgLogger.INFO,
+ '4': pkgLogger.WARNING,
+ '5': pkgLogger.ERROR,
+}
+
+func (d *Dispatcher) processLogMessage(message string) (string, error) {
+ if len(message) < 3 {
+ return "", errors.New("Invalid Log Message: " + message)
+ }
+
+ messageText := message[2:]
+
+ switch message[1] {
+ case 'T':
+ d.log.Trace(messageText)
+ case 'P':
+ d.log.Print(messageText)
+ case 'D':
+ d.log.Debug(messageText)
+ case 'I':
+ d.log.Info(messageText)
+ case 'W':
+ d.log.Warning(messageText)
+ case 'E':
+ d.log.Error(messageText)
+ case 'F':
+ d.log.Fatal(messageText)
+ case 'S':
+ loglevel, exists := logLevelMap[message[2]]
+ if !exists {
+ return "", errors.New("Invalid Set Log Level Message: " + message)
+ }
+ d.log.SetLogLevel(loglevel)
+ default:
+ return "", errors.New("Invalid Log Message: " + message)
+ }
+ return "", nil
+}
diff --git a/v2/internal/frontend/dispatcher/systemcalls.go b/v2/internal/frontend/dispatcher/systemcalls.go
new file mode 100644
index 000000000..8d23d54bf
--- /dev/null
+++ b/v2/internal/frontend/dispatcher/systemcalls.go
@@ -0,0 +1,38 @@
+package dispatcher
+
+import (
+ "fmt"
+ "strings"
+
+ "github.com/wailsapp/wails/v2/internal/frontend"
+)
+
+const systemCallPrefix = ":wails:"
+
+type position struct {
+ X int `json:"x"`
+ Y int `json:"y"`
+}
+
+type size struct {
+ W int `json:"w"`
+ H int `json:"h"`
+}
+
+func (d *Dispatcher) processSystemCall(payload callMessage, sender frontend.Frontend) (interface{}, error) {
+
+ // Strip prefix
+ name := strings.TrimPrefix(payload.Name, systemCallPrefix)
+
+ switch name {
+ case "WindowGetPos":
+ x, y := sender.WindowGetPos()
+ return &position{x, y}, nil
+ case "WindowGetSize":
+ w, h := sender.WindowGetSize()
+ return &size{w, h}, nil
+ default:
+ return nil, fmt.Errorf("unknown systemcall message: %s", payload.Name)
+ }
+
+}
diff --git a/v2/internal/frontend/dispatcher/window.go b/v2/internal/frontend/dispatcher/window.go
new file mode 100644
index 000000000..204eefbd5
--- /dev/null
+++ b/v2/internal/frontend/dispatcher/window.go
@@ -0,0 +1,79 @@
+package dispatcher
+
+import (
+ "encoding/json"
+ "errors"
+ "github.com/wailsapp/wails/v2/internal/frontend"
+ "github.com/wailsapp/wails/v2/pkg/options"
+ "strconv"
+ "strings"
+)
+
+func (d *Dispatcher) mustAtoI(input string) int {
+ result, err := strconv.Atoi(input)
+ if err != nil {
+ d.log.Error("cannot convert %s to integer!", input)
+ }
+ return result
+}
+
+func (d *Dispatcher) processWindowMessage(message string, sender frontend.Frontend) (string, error) {
+ if len(message) < 2 {
+ return "", errors.New("Invalid Event Message: " + message)
+ }
+
+ switch message[1] {
+ case 'c':
+ go sender.WindowCenter()
+ case 'T':
+ title := message[2:]
+ go sender.WindowSetTitle(title)
+ case 'F':
+ go sender.WindowFullscreen()
+ case 'f':
+ go sender.WindowUnFullscreen()
+ case 's':
+ parts := strings.Split(message[3:], ":")
+ w := d.mustAtoI(parts[0])
+ h := d.mustAtoI(parts[1])
+ go sender.WindowSetSize(w, h)
+ case 'p':
+ parts := strings.Split(message[3:], ":")
+ x := d.mustAtoI(parts[0])
+ y := d.mustAtoI(parts[1])
+ go sender.WindowSetPos(x, y)
+ case 'H':
+ go sender.WindowHide()
+ case 'S':
+ go sender.WindowShow()
+ case 'r':
+ var rgba options.RGBA
+ err := json.Unmarshal([]byte(message[3:]), &rgba)
+ if err != nil {
+ return "", err
+ }
+ go sender.WindowSetRGBA(&rgba)
+ case 'M':
+ go sender.WindowMaximise()
+ case 'U':
+ go sender.WindowUnmaximise()
+ case 'm':
+ go sender.WindowMinimise()
+ case 'u':
+ go sender.WindowUnminimise()
+ case 'Z':
+ parts := strings.Split(message[3:], ":")
+ w := d.mustAtoI(parts[0])
+ h := d.mustAtoI(parts[1])
+ go sender.WindowSetMaxSize(w, h)
+ case 'z':
+ parts := strings.Split(message[3:], ":")
+ w := d.mustAtoI(parts[0])
+ h := d.mustAtoI(parts[1])
+ go sender.WindowSetMinSize(w, h)
+ default:
+ d.log.Error("unknown Window message: %s", message)
+ }
+
+ return "", nil
+}
diff --git a/v2/internal/frontend/events.go b/v2/internal/frontend/events.go
new file mode 100644
index 000000000..484e3607a
--- /dev/null
+++ b/v2/internal/frontend/events.go
@@ -0,0 +1,10 @@
+package frontend
+
+type Events interface {
+ On(eventName string, callback func(...interface{}))
+ OnMultiple(eventName string, callback func(...interface{}), counter int)
+ Once(eventName string, callback func(...interface{}))
+ Emit(eventName string, data ...interface{})
+ Off(eventName string)
+ Notify(sender Frontend, name string, data ...interface{})
+}
diff --git a/v2/internal/frontend/frontend.go b/v2/internal/frontend/frontend.go
new file mode 100644
index 000000000..2a4862868
--- /dev/null
+++ b/v2/internal/frontend/frontend.go
@@ -0,0 +1,105 @@
+package frontend
+
+import (
+ "context"
+
+ "github.com/wailsapp/wails/v2/pkg/menu"
+ "github.com/wailsapp/wails/v2/pkg/options"
+)
+
+// FileFilter defines a filter for dialog boxes
+type FileFilter struct {
+ DisplayName string // Filter information EG: "Image Files (*.jpg, *.png)"
+ Pattern string // semi-colon separated list of extensions, EG: "*.jpg;*.png"
+}
+
+// OpenDialogOptions contains the options for the OpenDialogOptions runtime method
+type OpenDialogOptions struct {
+ DefaultDirectory string
+ DefaultFilename string
+ Title string
+ Filters []FileFilter
+ AllowFiles bool
+ AllowDirectories bool
+ ShowHiddenFiles bool
+ CanCreateDirectories bool
+ ResolvesAliases bool
+ TreatPackagesAsDirectories bool
+}
+
+// SaveDialogOptions contains the options for the SaveDialog runtime method
+type SaveDialogOptions struct {
+ DefaultDirectory string
+ DefaultFilename string
+ Title string
+ Filters []FileFilter
+ ShowHiddenFiles bool
+ CanCreateDirectories bool
+ TreatPackagesAsDirectories bool
+}
+
+type DialogType string
+
+const (
+ InfoDialog DialogType = "info"
+ WarningDialog DialogType = "warning"
+ ErrorDialog DialogType = "error"
+ QuestionDialog DialogType = "question"
+)
+
+// MessageDialogOptions contains the options for the Message dialogs, EG Info, Warning, etc runtime methods
+type MessageDialogOptions struct {
+ Type DialogType
+ Title string
+ Message string
+ Buttons []string
+ DefaultButton string
+ CancelButton string
+ Icon string
+}
+
+type Frontend interface {
+ Run(context.Context) error
+ Quit()
+
+ // Dialog
+ OpenFileDialog(dialogOptions OpenDialogOptions) (string, error)
+ OpenMultipleFilesDialog(dialogOptions OpenDialogOptions) ([]string, error)
+ OpenDirectoryDialog(dialogOptions OpenDialogOptions) (string, error)
+ SaveFileDialog(dialogOptions SaveDialogOptions) (string, error)
+ MessageDialog(dialogOptions MessageDialogOptions) (string, error)
+
+ // Window
+ WindowSetTitle(title string)
+ WindowShow()
+ WindowHide()
+ WindowCenter()
+ WindowMaximise()
+ WindowUnmaximise()
+ WindowMinimise()
+ WindowUnminimise()
+ WindowSetPos(x int, y int)
+ WindowGetPos() (int, int)
+ WindowSetSize(width int, height int)
+ WindowGetSize() (int, int)
+ WindowSetMinSize(width int, height int)
+ WindowSetMaxSize(width int, height int)
+ WindowFullscreen()
+ WindowUnFullscreen()
+ WindowSetRGBA(col *options.RGBA)
+ WindowReload()
+
+ // Menus
+ MenuSetApplicationMenu(menu *menu.Menu)
+ MenuUpdateApplicationMenu()
+ //SetTrayMenu(menu *menu.TrayMenu)
+ //UpdateTrayMenuLabel(menu *menu.TrayMenu)
+ //UpdateContextMenu(contextMenu *menu.ContextMenu)
+ //DeleteTrayMenuByID(id string)
+
+ // Events
+ Notify(name string, data ...interface{})
+
+ // Browser
+ BrowserOpenURL(url string)
+}
diff --git a/v2/internal/frontend/runtime/desktop/bindings.js b/v2/internal/frontend/runtime/desktop/bindings.js
new file mode 100644
index 000000000..96e1890f6
--- /dev/null
+++ b/v2/internal/frontend/runtime/desktop/bindings.js
@@ -0,0 +1,67 @@
+/*
+ _ __ _ __
+| | / /___ _(_) /____
+| | /| / / __ `/ / / ___/
+| |/ |/ / /_/ / / (__ )
+|__/|__/\__,_/_/_/____/
+The electron alternative for Go
+(c) Lea Anthony 2019-present
+*/
+/* jshint esversion: 6 */
+
+import {Call} from './calls';
+
+// This is where we bind go method wrappers
+window.go = {};
+
+export function SetBindings(bindingsMap) {
+ try {
+ bindingsMap = JSON.parse(bindingsMap);
+ } catch (e) {
+ console.error(e);
+ }
+
+ // Initialise the bindings map
+ window.go = window.go || {};
+
+ // Iterate package names
+ Object.keys(bindingsMap).forEach((packageName) => {
+
+ // Create inner map if it doesn't exist
+ window.go[packageName] = window.go[packageName] || {};
+
+ // Iterate struct names
+ Object.keys(bindingsMap[packageName]).forEach((structName) => {
+
+ // Create inner map if it doesn't exist
+ window.go[packageName][structName] = window.go[packageName][structName] || {};
+
+ Object.keys(bindingsMap[packageName][structName]).forEach((methodName) => {
+
+ window.go[packageName][structName][methodName] = function () {
+
+ // No timeout by default
+ let timeout = 0;
+
+ // Actual function
+ function dynamic() {
+ const args = [].slice.call(arguments);
+ return Call([packageName, structName, methodName].join('.'), args, timeout);
+ }
+
+ // Allow setting timeout to function
+ dynamic.setTimeout = function (newTimeout) {
+ timeout = newTimeout;
+ };
+
+ // Allow getting timeout to function
+ dynamic.getTimeout = function () {
+ return timeout;
+ };
+
+ return dynamic;
+ }();
+ });
+ });
+ });
+}
diff --git a/v2/internal/frontend/runtime/desktop/browser.js b/v2/internal/frontend/runtime/desktop/browser.js
new file mode 100644
index 000000000..18c5258f2
--- /dev/null
+++ b/v2/internal/frontend/runtime/desktop/browser.js
@@ -0,0 +1,8 @@
+/**
+ * @description: Use the system default browser to open the url
+ * @param {string} url
+ * @return {void}
+ */
+export function BrowserOpenURL(url) {
+ window.WailsInvoke('BO:' + url);
+}
\ No newline at end of file
diff --git a/v2/internal/frontend/runtime/desktop/calls.js b/v2/internal/frontend/runtime/desktop/calls.js
new file mode 100644
index 000000000..7b20cadb7
--- /dev/null
+++ b/v2/internal/frontend/runtime/desktop/calls.js
@@ -0,0 +1,142 @@
+/*
+ _ __ _ __
+| | / /___ _(_) /____
+| | /| / / __ `/ / / ___/
+| |/ |/ / /_/ / / (__ )
+|__/|__/\__,_/_/_/____/
+The electron alternative for Go
+(c) Lea Anthony 2019-present
+*/
+/* jshint esversion: 6 */
+
+export const callbacks = {};
+
+/**
+ * Returns a number from the native browser random function
+ *
+ * @returns number
+ */
+function cryptoRandom() {
+ var array = new Uint32Array(1);
+ return window.crypto.getRandomValues(array)[0];
+}
+
+/**
+ * Returns a number using da old-skool Math.Random
+ * I likes to call it LOLRandom
+ *
+ * @returns number
+ */
+function basicRandom() {
+ return Math.random() * 9007199254740991;
+}
+
+// Pick a random number function based on browser capability
+var randomFunc;
+if (window.crypto) {
+ randomFunc = cryptoRandom;
+} else {
+ randomFunc = basicRandom;
+}
+
+
+/**
+ * Call sends a message to the backend to call the binding with the
+ * given data. A promise is returned and will be completed when the
+ * backend responds. This will be resolved when the call was successful
+ * or rejected if an error is passed back.
+ * There is a timeout mechanism. If the call doesn't respond in the given
+ * time (in milliseconds) then the promise is rejected.
+ *
+ * @export
+ * @param {string} name
+ * @param {any=} args
+ * @param {number=} timeout
+ * @returns
+ */
+export function Call(name, args, timeout) {
+
+ // Timeout infinite by default
+ if (timeout == null) {
+ timeout = 0;
+ }
+
+ // Create a promise
+ return new Promise(function (resolve, reject) {
+
+ // Create a unique callbackID
+ var callbackID;
+ do {
+ callbackID = name + '-' + randomFunc();
+ } while (callbacks[callbackID]);
+
+ var timeoutHandle;
+ // Set timeout
+ if (timeout > 0) {
+ timeoutHandle = setTimeout(function () {
+ reject(Error('Call to ' + name + ' timed out. Request ID: ' + callbackID));
+ }, timeout);
+ }
+
+ // Store callback
+ callbacks[callbackID] = {
+ timeoutHandle: timeoutHandle,
+ reject: reject,
+ resolve: resolve
+ };
+
+ try {
+ const payload = {
+ name,
+ args,
+ callbackID,
+ };
+
+ // Make the call
+ window.WailsInvoke('C' + JSON.stringify(payload));
+ } catch (e) {
+ // eslint-disable-next-line
+ console.error(e);
+ }
+ });
+}
+
+
+
+/**
+ * Called by the backend to return data to a previously called
+ * binding invocation
+ *
+ * @export
+ * @param {string} incomingMessage
+ */
+export function Callback(incomingMessage) {
+ // Decode the message - Credit: https://stackoverflow.com/a/13865680
+ //incomingMessage = decodeURIComponent(incomingMessage.replace(/\s+/g, '').replace(/[0-9a-f]{2}/g, '%$&'));
+
+ // Parse the message
+ var message;
+ try {
+ message = JSON.parse(incomingMessage);
+ } catch (e) {
+ const error = `Invalid JSON passed to callback: ${e.message}. Message: ${incomingMessage}`;
+ wails.LogDebug(error);
+ throw new Error(error);
+ }
+ var callbackID = message.callbackid;
+ var callbackData = callbacks[callbackID];
+ if (!callbackData) {
+ const error = `Callback '${callbackID}' not registered!!!`;
+ console.error(error); // eslint-disable-line
+ throw new Error(error);
+ }
+ clearTimeout(callbackData.timeoutHandle);
+
+ delete callbacks[callbackID];
+
+ if (message.error) {
+ callbackData.reject(message.error);
+ } else {
+ callbackData.resolve(message.result);
+ }
+}
diff --git a/v2/internal/frontend/runtime/desktop/events.js b/v2/internal/frontend/runtime/desktop/events.js
new file mode 100644
index 000000000..464a72c55
--- /dev/null
+++ b/v2/internal/frontend/runtime/desktop/events.js
@@ -0,0 +1,159 @@
+/*
+ _ __ _ __
+| | / /___ _(_) /____
+| | /| / / __ `/ / / ___/
+| |/ |/ / /_/ / / (__ )
+|__/|__/\__,_/_/_/____/
+The electron alternative for Go
+(c) Lea Anthony 2019-present
+*/
+/* jshint esversion: 6 */
+
+// Defines a single listener with a maximum number of times to callback
+
+/**
+ * The Listener class defines a listener! :-)
+ *
+ * @class Listener
+ */
+class Listener {
+ /**
+ * Creates an instance of Listener.
+ * @param {function} callback
+ * @param {number} maxCallbacks
+ * @memberof Listener
+ */
+ constructor(callback, maxCallbacks) {
+ // Default of -1 means infinite
+ maxCallbacks = maxCallbacks || -1;
+ // Callback invokes the callback with the given data
+ // Returns true if this listener should be destroyed
+ this.Callback = (data) => {
+ callback.apply(null, data);
+ // If maxCallbacks is infinite, return false (do not destroy)
+ if (maxCallbacks === -1) {
+ return false;
+ }
+ // Decrement maxCallbacks. Return true if now 0, otherwise false
+ maxCallbacks -= 1;
+ return maxCallbacks === 0;
+ };
+ }
+}
+
+export const eventListeners = {};
+
+/**
+ * Registers an event listener that will be invoked `maxCallbacks` times before being destroyed
+ *
+ * @export
+ * @param {string} eventName
+ * @param {function} callback
+ * @param {number} maxCallbacks
+ */
+export function EventsOnMultiple(eventName, callback, maxCallbacks) {
+ eventListeners[eventName] = eventListeners[eventName] || [];
+ const thisListener = new Listener(callback, maxCallbacks);
+ eventListeners[eventName].push(thisListener);
+}
+
+/**
+ * Registers an event listener that will be invoked every time the event is emitted
+ *
+ * @export
+ * @param {string} eventName
+ * @param {function} callback
+ */
+export function EventsOn(eventName, callback) {
+ EventsOnMultiple(eventName, callback, -1);
+}
+
+/**
+ * Registers an event listener that will be invoked once then destroyed
+ *
+ * @export
+ * @param {string} eventName
+ * @param {function} callback
+ */
+export function EventsOnce(eventName, callback) {
+ EventsOnMultiple(eventName, callback, 1);
+}
+
+function notifyListeners(eventData) {
+
+ // Get the event name
+ let eventName = eventData.name;
+
+ // Check if we have any listeners for this event
+ if (eventListeners[eventName]) {
+
+ // Keep a list of listener indexes to destroy
+ const newEventListenerList = eventListeners[eventName].slice();
+
+ // Iterate listeners
+ for (let count = 0; count < eventListeners[eventName].length; count += 1) {
+
+ // Get next listener
+ const listener = eventListeners[eventName][count];
+
+ let data = eventData.data;
+
+ // Do the callback
+ const destroy = listener.Callback(data);
+ if (destroy) {
+ // if the listener indicated to destroy itself, add it to the destroy list
+ newEventListenerList.splice(count, 1);
+ }
+ }
+
+ // Update callbacks with new list of listeners
+ eventListeners[eventName] = newEventListenerList;
+ }
+}
+
+/**
+ * Notify informs frontend listeners that an event was emitted with the given data
+ *
+ * @export
+ * @param {string} notifyMessage - encoded notification message
+
+ */
+export function EventsNotify(notifyMessage) {
+ // Parse the message
+ let message;
+ try {
+ message = JSON.parse(notifyMessage);
+ } catch (e) {
+ const error = 'Invalid JSON passed to Notify: ' + notifyMessage;
+ throw new Error(error);
+ }
+ notifyListeners(message);
+}
+
+/**
+ * Emit an event with the given name and data
+ *
+ * @export
+ * @param {string} eventName
+ */
+export function EventsEmit(eventName) {
+
+ const payload = {
+ name: eventName,
+ data: [].slice.apply(arguments).slice(1),
+ };
+
+ // Notify JS listeners
+ notifyListeners(payload);
+
+ // Notify Go listeners
+ window.WailsInvoke('EE' + JSON.stringify(payload));
+}
+
+export function EventsOff(eventName) {
+ // Remove local listeners
+ eventListeners.delete(eventName);
+
+ // Notify Go listeners
+ window.WailsInvoke('EX' + eventName);
+}
\ No newline at end of file
diff --git a/v2/internal/frontend/runtime/desktop/ipc.js b/v2/internal/frontend/runtime/desktop/ipc.js
new file mode 100644
index 000000000..fee96ac38
--- /dev/null
+++ b/v2/internal/frontend/runtime/desktop/ipc.js
@@ -0,0 +1,39 @@
+/*
+ _ __ _ __
+| | / /___ _(_) /____
+| | /| / / __ `/ / / ___/
+| |/ |/ / /_/ / / (__ )
+|__/|__/\__,_/_/_/____/
+The electron alternative for Go
+(c) Lea Anthony 2019-present
+*/
+/* jshint esversion: 6 */
+
+/**
+ * WailsInvoke sends the given message to the backend
+ *
+ * @param {string} message
+ */
+
+(function () {
+ // Credit: https://stackoverflow.com/a/2631521
+ let _deeptest = function (s) {
+ var obj = window[s.shift()];
+ while (obj && s.length) obj = obj[s.shift()];
+ return obj;
+ };
+ let windows = _deeptest(["chrome", "webview", "postMessage"]);
+ let mac = _deeptest(["webkit", "messageHandlers", "external", "postMessage"]);
+
+ if (!windows && !mac) {
+ console.error("Unsupported Platform");
+ return;
+ }
+
+ if (windows) {
+ window.WailsInvoke = (message) => window.chrome.webview.postMessage(message);
+ }
+ if (mac) {
+ window.WailsInvoke = (message) => window.webkit.messageHandlers.external.postMessage(message);
+ }
+})();
\ No newline at end of file
diff --git a/v2/internal/frontend/runtime/desktop/log.js b/v2/internal/frontend/runtime/desktop/log.js
new file mode 100644
index 000000000..ff52f5919
--- /dev/null
+++ b/v2/internal/frontend/runtime/desktop/log.js
@@ -0,0 +1,113 @@
+/*
+ _ __ _ __
+| | / /___ _(_) /____
+| | /| / / __ `/ / / ___/
+| |/ |/ / /_/ / / (__ )
+|__/|__/\__,_/_/_/____/
+The electron alternative for Go
+(c) Lea Anthony 2019-present
+*/
+
+/* jshint esversion: 6 */
+
+/**
+ * Sends a log message to the backend with the given level + message
+ *
+ * @param {string} level
+ * @param {string} message
+ */
+function sendLogMessage(level, message) {
+
+ // Log Message format:
+ // l[type][message]
+ window.WailsInvoke('L' + level + message);
+}
+
+/**
+ * Log the given trace message with the backend
+ *
+ * @export
+ * @param {string} message
+ */
+export function LogTrace(message) {
+ sendLogMessage('T', message);
+}
+
+/**
+ * Log the given message with the backend
+ *
+ * @export
+ * @param {string} message
+ */
+export function LogPrint(message) {
+ sendLogMessage('P', message);
+}
+
+/**
+ * Log the given debug message with the backend
+ *
+ * @export
+ * @param {string} message
+ */
+export function LogDebug(message) {
+ sendLogMessage('D', message);
+}
+
+/**
+ * Log the given info message with the backend
+ *
+ * @export
+ * @param {string} message
+ */
+export function LogInfo(message) {
+ sendLogMessage('I', message);
+}
+
+/**
+ * Log the given warning message with the backend
+ *
+ * @export
+ * @param {string} message
+ */
+export function LogWarning(message) {
+ sendLogMessage('W', message);
+}
+
+/**
+ * Log the given error message with the backend
+ *
+ * @export
+ * @param {string} message
+ */
+export function LogError(message) {
+ sendLogMessage('E', message);
+}
+
+/**
+ * Log the given fatal message with the backend
+ *
+ * @export
+ * @param {string} message
+ */
+export function LogFatal(message) {
+ sendLogMessage('F', message);
+}
+
+/**
+ * Sets the Log level to the given log level
+ *
+ * @export
+ * @param {number} loglevel
+ */
+export function SetLogLevel(loglevel) {
+ sendLogMessage('S', loglevel);
+}
+
+// Log levels
+export const LogLevel = {
+ TRACE: 1,
+ DEBUG: 2,
+ INFO: 3,
+ WARNING: 4,
+ ERROR: 5,
+};
diff --git a/v2/internal/frontend/runtime/desktop/main.js b/v2/internal/frontend/runtime/desktop/main.js
new file mode 100644
index 000000000..5e0b6feb5
--- /dev/null
+++ b/v2/internal/frontend/runtime/desktop/main.js
@@ -0,0 +1,87 @@
+/*
+ _ __ _ __
+| | / /___ _(_) /____
+| | /| / / __ `/ / / ___/
+| |/ |/ / /_/ / / (__ )
+|__/|__/\__,_/_/_/____/
+The electron alternative for Go
+(c) Lea Anthony 2019-present
+*/
+/* jshint esversion: 9 */
+import * as Log from './log';
+import {eventListeners, EventsEmit, EventsNotify, EventsOff, EventsOn, EventsOnce, EventsOnMultiple} from './events';
+import {Callback, callbacks} from './calls';
+import {SetBindings} from "./bindings";
+import * as Window from "./window";
+import * as Browser from "./browser";
+
+
+export function Quit() {
+ window.WailsInvoke('Q');
+}
+
+// The JS runtime
+window.runtime = {
+ ...Log,
+ ...Window,
+ ...Browser,
+ EventsOn,
+ EventsOnce,
+ EventsOnMultiple,
+ EventsEmit,
+ EventsOff,
+ Quit
+};
+
+// Internal wails endpoints
+window.wails = {
+ Callback,
+ EventsNotify,
+ SetBindings,
+ eventListeners,
+ callbacks,
+ flags: {
+ disableScrollbarDrag: false,
+ disableWailsDefaultContextMenu: false,
+ }
+};
+
+// Set the bindings
+window.wails.SetBindings(window.wailsbindings);
+delete window.wails.SetBindings;
+
+// This is evaluated at build time in package.json
+// const dev = 0;
+// const production = 1;
+if (ENV === 0) {
+ delete window.wailsbindings;
+}
+
+// Setup drag handler
+// Based on code from: https://github.com/patr0nus/DeskGap
+window.addEventListener('mousedown', (e) => {
+ let currentElement = e.target;
+ while (currentElement != null) {
+ if (currentElement.hasAttribute('data-wails-no-drag')) {
+ break;
+ } else if (currentElement.hasAttribute('data-wails-drag')) {
+ if (window.wails.flags.disableScrollbarDrag) {
+ // This checks for clicks on the scroll bar
+ if (e.offsetX > e.target.clientWidth || e.offsetY > e.target.clientHeight) {
+ break;
+ }
+ }
+ window.WailsInvoke("drag");
+ e.preventDefault();
+ break;
+ }
+ currentElement = currentElement.parentElement;
+ }
+});
+
+// Setup context menu hook
+window.addEventListener('contextmenu', function (e) {
+ if (window.wails.flags.disableWailsDefaultContextMenu) {
+ e.preventDefault();
+ }
+});
\ No newline at end of file
diff --git a/v2/internal/frontend/runtime/desktop/window.js b/v2/internal/frontend/runtime/desktop/window.js
new file mode 100644
index 000000000..448dc5e3d
--- /dev/null
+++ b/v2/internal/frontend/runtime/desktop/window.js
@@ -0,0 +1,187 @@
+/*
+ _ __ _ __
+| | / /___ _(_) /____
+| | /| / / __ `/ / / ___/
+| |/ |/ / /_/ / / (__ )
+|__/|__/\__,_/_/_/____/
+The electron alternative for Go
+(c) Lea Anthony 2019-present
+*/
+
+/* jshint esversion: 9 */
+
+
+import {Call} from "./calls";
+
+export function WindowReload() {
+ window.location.reload();
+}
+
+/**
+ * Place the window in the center of the screen
+ *
+ * @export
+ */
+export function WindowCenter() {
+ window.WailsInvoke('Wc');
+}
+
+/**
+ * Sets the window title
+ *
+ * @param {string} title
+ * @export
+ */
+export function WindowSetTitle(title) {
+ window.WailsInvoke('WT' + title);
+}
+
+/**
+ * Makes the window go fullscreen
+ *
+ * @export
+ */
+export function WindowFullscreen() {
+ window.WailsInvoke('WF');
+}
+
+/**
+ * Reverts the window from fullscreen
+ *
+ * @export
+ */
+export function WindowUnFullscreen() {
+ window.WailsInvoke('Wf');
+}
+
+/**
+ * Set the Size of the window
+ *
+ * @export
+ * @param {number} width
+ * @param {number} height
+ */
+export function WindowSetSize(width, height) {
+ window.WailsInvoke('Ws:' + width + ':' + height);
+}
+
+/**
+ * Get the Size of the window
+ *
+ * @export
+ * @return {Promise<{w: number, h: number}>} The size of the window
+
+ */
+export function WindowGetSize() {
+ return Call(":wails:WindowGetSize");
+}
+
+/**
+ * Set the maximum size of the window
+ *
+ * @export
+ * @param {number} width
+ * @param {number} height
+ */
+export function WindowSetMaxSize(width, height) {
+ window.WailsInvoke('WZ:' + width + ':' + height);
+}
+
+/**
+ * Set the minimum size of the window
+ *
+ * @export
+ * @param {number} width
+ * @param {number} height
+ */
+export function WindowSetMinSize(width, height) {
+ window.WailsInvoke('Wz:' + width + ':' + height);
+}
+
+/**
+ * Set the Position of the window
+ *
+ * @export
+ * @param {number} x
+ * @param {number} y
+ */
+export function WindowSetPosition(x, y) {
+ window.WailsInvoke('Wp:' + x + ':' + y);
+}
+
+/**
+ * Get the Position of the window
+ *
+ * @export
+ * @return {Promise<{x: number, y: number}>} The position of the window
+ */
+export function WindowGetPosition() {
+ return Call(":wails:WindowGetPos");
+}
+
+/**
+ * Hide the Window
+ *
+ * @export
+ */
+export function WindowHide() {
+ window.WailsInvoke('WH');
+}
+
+/**
+ * Show the Window
+ *
+ * @export
+ */
+export function WindowShow() {
+ window.WailsInvoke('WS');
+}
+
+/**
+ * Maximise the Window
+ *
+ * @export
+ */
+export function WindowMaximise() {
+ window.WailsInvoke('WM');
+}
+
+/**
+ * Unmaximise the Window
+ *
+ * @export
+ */
+export function WindowUnmaximise() {
+ window.WailsInvoke('WU');
+}
+
+/**
+ * Minimise the Window
+ *
+ * @export
+ */
+export function WindowMinimise() {
+ window.WailsInvoke('Wm');
+}
+
+/**
+ * Unminimise the Window
+ *
+ * @export
+ */
+export function WindowUnminimise() {
+ window.WailsInvoke('Wu');
+}
+
+
+/**
+ * Sets the background colour of the window
+ *
+ * @export
+ * @param {RGBA} RGBA background colour
+ */
+export function WindowSetRGBA(RGBA) {
+ let rgba = JSON.stringify(RGBA);
+ window.WailsInvoke('Wr:' + rgba);
+}
+
diff --git a/v2/internal/frontend/runtime/dev/Overlay.svelte b/v2/internal/frontend/runtime/dev/Overlay.svelte
new file mode 100644
index 000000000..dfe02b21b
--- /dev/null
+++ b/v2/internal/frontend/runtime/dev/Overlay.svelte
@@ -0,0 +1,54 @@
+
+
+{#if $overlayVisible }
+
+{/if}
+
+
\ No newline at end of file
diff --git a/v2/internal/frontend/runtime/dev/build.js b/v2/internal/frontend/runtime/dev/build.js
new file mode 100644
index 000000000..6e5e8bb2f
--- /dev/null
+++ b/v2/internal/frontend/runtime/dev/build.js
@@ -0,0 +1,15 @@
+/* jshint esversion: 8 */
+const esbuild = require("esbuild");
+const sveltePlugin = require("esbuild-svelte");
+
+esbuild
+ .build({
+ entryPoints: ["main.js"],
+ bundle: true,
+ minify: true,
+ outfile: "../ipc_websocket.js",
+ plugins: [sveltePlugin({compileOptions: {css: true}})],
+ logLevel: "info",
+ sourcemap: "inline",
+ })
+ .catch(() => process.exit(1));
\ No newline at end of file
diff --git a/v2/internal/frontend/runtime/dev/log.js b/v2/internal/frontend/runtime/dev/log.js
new file mode 100644
index 000000000..e128c97f0
--- /dev/null
+++ b/v2/internal/frontend/runtime/dev/log.js
@@ -0,0 +1,8 @@
+export function log(message) {
+ // eslint-disable-next-line
+ console.log(
+ '%c wails dev %c ' + message + ' ',
+ 'background: #aa0000; color: #fff; border-radius: 3px 0px 0px 3px; padding: 1px; font-size: 0.7rem',
+ 'background: #009900; color: #fff; border-radius: 0px 3px 3px 0px; padding: 1px; font-size: 0.7rem'
+ );
+}
\ No newline at end of file
diff --git a/v2/internal/frontend/runtime/dev/main.js b/v2/internal/frontend/runtime/dev/main.js
new file mode 100644
index 000000000..dac1a8782
--- /dev/null
+++ b/v2/internal/frontend/runtime/dev/main.js
@@ -0,0 +1,119 @@
+/*
+ _ __ _ __
+| | / /___ _(_) /____
+| | /| / / __ `/ / / ___/
+| |/ |/ / /_/ / / (__ )
+|__/|__/\__,_/_/_/____/
+The electron alternative for Go
+(c) Lea Anthony 2019-present
+*/
+/* jshint esversion: 6 */
+
+import {log} from "./log";
+import Overlay from "./Overlay.svelte";
+import {hideOverlay, showOverlay} from "./store";
+
+let components = {};
+window.ipcCallbacks = [];
+window.ipcCallbackNames = [];
+
+window.awaitIPC = (name, callback) => {
+ if (!window.ipcCallbacks) return callback;
+ log("Queuing '" + name + "' for execution once ipc ready.");
+ window.ipcCallbackNames.push(name);
+ window.ipcCallbacks.push(callback);
+};
+
+window.addEventListener('DOMContentLoaded', () => {
+ components.overlay = new Overlay({
+ target: document.body,
+ anchor: document.querySelector('#wails-spinner'),
+ });
+});
+
+let websocket = null;
+let connectTimer;
+
+window.onbeforeunload = function () {
+ if (websocket) {
+ websocket.onclose = function () {
+ };
+ websocket.close();
+ websocket = null;
+ }
+};
+
+// ...and attempt to connect
+connect();
+
+function setupIPCBridge() {
+ window.WailsInvoke = (message) => {
+ websocket.send(message);
+ };
+ for (let i = 0; i < window.ipcCallbacks.length; i++) {
+ log("Executing JS: " + window.ipcCallbackNames[i]);
+ window.ipcCallbacks[i]();
+ }
+ delete window.ipcCallbacks;
+ delete window.ipcCallbackNames;
+}
+
+// Handles incoming websocket connections
+function handleConnect() {
+ log('Connected to backend');
+ hideOverlay();
+ setupIPCBridge();
+ clearInterval(connectTimer);
+ websocket.onclose = handleDisconnect;
+ websocket.onmessage = handleMessage;
+}
+
+// Handles websocket disconnects
+function handleDisconnect() {
+ log('Disconnected from backend');
+ websocket = null;
+ showOverlay();
+ connect();
+}
+
+function _connect() {
+ if (websocket == null) {
+ websocket = new WebSocket('ws://' + window.location.hostname + ':34115/wails/ipc');
+ websocket.onopen = handleConnect;
+ websocket.onerror = function (e) {
+ e.stopImmediatePropagation();
+ e.stopPropagation();
+ e.preventDefault();
+ websocket = null;
+ return false;
+ };
+ }
+}
+
+// Try to connect to the backend every .5s
+function connect() {
+ _connect();
+ connectTimer = setInterval(_connect, 500);
+}
+
+function handleMessage(message) {
+
+ if (message.data === "reload") {
+ window.runtime.WindowReload();
+ return;
+ }
+
+ // As a bridge we ignore js and css injections
+ switch (message.data[0]) {
+ // Notifications
+ case 'n':
+ window.wails.EventsNotify(message.data.slice(1));
+ break;
+ case 'c':
+ const callbackData = message.data.slice(1);
+ window.wails.Callback(callbackData);
+ break;
+ default:
+ log('Unknown message: ' + message.data);
+ }
+}
diff --git a/v2/internal/frontend/runtime/dev/package-lock.json b/v2/internal/frontend/runtime/dev/package-lock.json
new file mode 100644
index 000000000..4413e7f6b
--- /dev/null
+++ b/v2/internal/frontend/runtime/dev/package-lock.json
@@ -0,0 +1,667 @@
+{
+ "name": "dev",
+ "version": "2.0.0",
+ "lockfileVersion": 1,
+ "requires": true,
+ "dependencies": {
+ "ansi-styles": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
+ "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+ "dev": true,
+ "requires": {
+ "color-convert": "^1.9.0"
+ }
+ },
+ "balanced-match": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+ "dev": true
+ },
+ "brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "dev": true,
+ "requires": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "call-bind": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz",
+ "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==",
+ "dev": true,
+ "requires": {
+ "function-bind": "^1.1.1",
+ "get-intrinsic": "^1.0.2"
+ }
+ },
+ "chalk": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+ "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
+ }
+ },
+ "color-convert": {
+ "version": "1.9.3",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
+ "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+ "dev": true,
+ "requires": {
+ "color-name": "1.1.3"
+ }
+ },
+ "color-name": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+ "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
+ "dev": true
+ },
+ "concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
+ "dev": true
+ },
+ "cross-spawn": {
+ "version": "6.0.5",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
+ "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==",
+ "dev": true,
+ "requires": {
+ "nice-try": "^1.0.4",
+ "path-key": "^2.0.1",
+ "semver": "^5.5.0",
+ "shebang-command": "^1.2.0",
+ "which": "^1.2.9"
+ }
+ },
+ "define-properties": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz",
+ "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==",
+ "dev": true,
+ "requires": {
+ "object-keys": "^1.0.12"
+ }
+ },
+ "error-ex": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
+ "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
+ "dev": true,
+ "requires": {
+ "is-arrayish": "^0.2.1"
+ }
+ },
+ "es-abstract": {
+ "version": "1.18.5",
+ "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.5.tgz",
+ "integrity": "sha512-DDggyJLoS91CkJjgauM5c0yZMjiD1uK3KcaCeAmffGwZ+ODWzOkPN4QwRbsK5DOFf06fywmyLci3ZD8jLGhVYA==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "es-to-primitive": "^1.2.1",
+ "function-bind": "^1.1.1",
+ "get-intrinsic": "^1.1.1",
+ "has": "^1.0.3",
+ "has-symbols": "^1.0.2",
+ "internal-slot": "^1.0.3",
+ "is-callable": "^1.2.3",
+ "is-negative-zero": "^2.0.1",
+ "is-regex": "^1.1.3",
+ "is-string": "^1.0.6",
+ "object-inspect": "^1.11.0",
+ "object-keys": "^1.1.1",
+ "object.assign": "^4.1.2",
+ "string.prototype.trimend": "^1.0.4",
+ "string.prototype.trimstart": "^1.0.4",
+ "unbox-primitive": "^1.0.1"
+ }
+ },
+ "es-to-primitive": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz",
+ "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==",
+ "dev": true,
+ "requires": {
+ "is-callable": "^1.1.4",
+ "is-date-object": "^1.0.1",
+ "is-symbol": "^1.0.2"
+ }
+ },
+ "esbuild": {
+ "version": "0.12.21",
+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.12.21.tgz",
+ "integrity": "sha512-7hyXbU3g94aREufI/5nls7Xcc+RGQeZWZApm6hoBaFvt2BPtpT4TjFMQ9Tb1jU8XyBGz00ShmiyflCogphMHFQ==",
+ "dev": true
+ },
+ "esbuild-svelte": {
+ "version": "0.5.6",
+ "resolved": "https://registry.npmjs.org/esbuild-svelte/-/esbuild-svelte-0.5.6.tgz",
+ "integrity": "sha512-Bz8nU45FrT6sP/Tf3M2rQUuBGxnDSNSPZNIoYwSNt5H+wjSyo/t+zm94tgnOZsR6GgpDMbNQgo4jGbK0NLvEfw==",
+ "dev": true,
+ "requires": {
+ "svelte": "^3.42.6"
+ },
+ "dependencies": {
+ "svelte": {
+ "version": "3.43.1",
+ "resolved": "https://registry.npmjs.org/svelte/-/svelte-3.43.1.tgz",
+ "integrity": "sha512-nvPIaKx4HLzYlSdquISZpgG1Kqr2VAWQjZOt3Iwm3UhbqmA0LnSx4k1YpRMEhjQYW3ZCqQoK8Egto9tv4YewMA==",
+ "dev": true
+ }
+ }
+ },
+ "escape-string-regexp": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+ "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
+ "dev": true
+ },
+ "function-bind": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
+ "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
+ "dev": true
+ },
+ "get-intrinsic": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz",
+ "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==",
+ "dev": true,
+ "requires": {
+ "function-bind": "^1.1.1",
+ "has": "^1.0.3",
+ "has-symbols": "^1.0.1"
+ }
+ },
+ "graceful-fs": {
+ "version": "4.2.8",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz",
+ "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==",
+ "dev": true
+ },
+ "has": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
+ "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
+ "dev": true,
+ "requires": {
+ "function-bind": "^1.1.1"
+ }
+ },
+ "has-bigints": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz",
+ "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==",
+ "dev": true
+ },
+ "has-flag": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+ "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
+ "dev": true
+ },
+ "has-symbols": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz",
+ "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==",
+ "dev": true
+ },
+ "has-tostringtag": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz",
+ "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==",
+ "dev": true,
+ "requires": {
+ "has-symbols": "^1.0.2"
+ }
+ },
+ "hosted-git-info": {
+ "version": "2.8.9",
+ "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz",
+ "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==",
+ "dev": true
+ },
+ "internal-slot": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz",
+ "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==",
+ "dev": true,
+ "requires": {
+ "get-intrinsic": "^1.1.0",
+ "has": "^1.0.3",
+ "side-channel": "^1.0.4"
+ }
+ },
+ "is-arrayish": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
+ "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=",
+ "dev": true
+ },
+ "is-bigint": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz",
+ "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==",
+ "dev": true,
+ "requires": {
+ "has-bigints": "^1.0.1"
+ }
+ },
+ "is-boolean-object": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz",
+ "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "has-tostringtag": "^1.0.0"
+ }
+ },
+ "is-callable": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz",
+ "integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==",
+ "dev": true
+ },
+ "is-core-module": {
+ "version": "2.6.0",
+ "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.6.0.tgz",
+ "integrity": "sha512-wShG8vs60jKfPWpF2KZRaAtvt3a20OAn7+IJ6hLPECpSABLcKtFKTTI4ZtH5QcBruBHlq+WsdHWyz0BCZW7svQ==",
+ "dev": true,
+ "requires": {
+ "has": "^1.0.3"
+ }
+ },
+ "is-date-object": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz",
+ "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==",
+ "dev": true,
+ "requires": {
+ "has-tostringtag": "^1.0.0"
+ }
+ },
+ "is-negative-zero": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.1.tgz",
+ "integrity": "sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w==",
+ "dev": true
+ },
+ "is-number-object": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.6.tgz",
+ "integrity": "sha512-bEVOqiRcvo3zO1+G2lVMy+gkkEm9Yh7cDMRusKKu5ZJKPUYSJwICTKZrNKHA2EbSP0Tu0+6B/emsYNHZyn6K8g==",
+ "dev": true,
+ "requires": {
+ "has-tostringtag": "^1.0.0"
+ }
+ },
+ "is-regex": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz",
+ "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "has-tostringtag": "^1.0.0"
+ }
+ },
+ "is-string": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz",
+ "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==",
+ "dev": true,
+ "requires": {
+ "has-tostringtag": "^1.0.0"
+ }
+ },
+ "is-symbol": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz",
+ "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==",
+ "dev": true,
+ "requires": {
+ "has-symbols": "^1.0.2"
+ }
+ },
+ "isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
+ "dev": true
+ },
+ "json-parse-better-errors": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz",
+ "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==",
+ "dev": true
+ },
+ "load-json-file": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz",
+ "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "^4.1.2",
+ "parse-json": "^4.0.0",
+ "pify": "^3.0.0",
+ "strip-bom": "^3.0.0"
+ }
+ },
+ "memorystream": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz",
+ "integrity": "sha1-htcJCzDORV1j+64S3aUaR93K+bI=",
+ "dev": true
+ },
+ "minimatch": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
+ "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
+ "dev": true,
+ "requires": {
+ "brace-expansion": "^1.1.7"
+ }
+ },
+ "nice-try": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz",
+ "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==",
+ "dev": true
+ },
+ "normalize-package-data": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz",
+ "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==",
+ "dev": true,
+ "requires": {
+ "hosted-git-info": "^2.1.4",
+ "resolve": "^1.10.0",
+ "semver": "2 || 3 || 4 || 5",
+ "validate-npm-package-license": "^3.0.1"
+ }
+ },
+ "npm-run-all": {
+ "version": "4.1.5",
+ "resolved": "https://registry.npmjs.org/npm-run-all/-/npm-run-all-4.1.5.tgz",
+ "integrity": "sha512-Oo82gJDAVcaMdi3nuoKFavkIHBRVqQ1qvMb+9LHk/cF4P6B2m8aP04hGf7oL6wZ9BuGwX1onlLhpuoofSyoQDQ==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^3.2.1",
+ "chalk": "^2.4.1",
+ "cross-spawn": "^6.0.5",
+ "memorystream": "^0.3.1",
+ "minimatch": "^3.0.4",
+ "pidtree": "^0.3.0",
+ "read-pkg": "^3.0.0",
+ "shell-quote": "^1.6.1",
+ "string.prototype.padend": "^3.0.0"
+ }
+ },
+ "object-inspect": {
+ "version": "1.11.0",
+ "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.11.0.tgz",
+ "integrity": "sha512-jp7ikS6Sd3GxQfZJPyH3cjcbJF6GZPClgdV+EFygjFLQ5FmW/dRUnTd9PQ9k0JhoNDabWFbpF1yCdSWCC6gexg==",
+ "dev": true
+ },
+ "object-keys": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
+ "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
+ "dev": true
+ },
+ "object.assign": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz",
+ "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.0",
+ "define-properties": "^1.1.3",
+ "has-symbols": "^1.0.1",
+ "object-keys": "^1.1.1"
+ }
+ },
+ "parse-json": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz",
+ "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=",
+ "dev": true,
+ "requires": {
+ "error-ex": "^1.3.1",
+ "json-parse-better-errors": "^1.0.1"
+ }
+ },
+ "path-key": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz",
+ "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=",
+ "dev": true
+ },
+ "path-parse": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
+ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
+ "dev": true
+ },
+ "path-type": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz",
+ "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==",
+ "dev": true,
+ "requires": {
+ "pify": "^3.0.0"
+ }
+ },
+ "pidtree": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.3.1.tgz",
+ "integrity": "sha512-qQbW94hLHEqCg7nhby4yRC7G2+jYHY4Rguc2bjw7Uug4GIJuu1tvf2uHaZv5Q8zdt+WKJ6qK1FOI6amaWUo5FA==",
+ "dev": true
+ },
+ "pify": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
+ "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=",
+ "dev": true
+ },
+ "read-pkg": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz",
+ "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=",
+ "dev": true,
+ "requires": {
+ "load-json-file": "^4.0.0",
+ "normalize-package-data": "^2.3.2",
+ "path-type": "^3.0.0"
+ }
+ },
+ "resolve": {
+ "version": "1.20.0",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz",
+ "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==",
+ "dev": true,
+ "requires": {
+ "is-core-module": "^2.2.0",
+ "path-parse": "^1.0.6"
+ }
+ },
+ "semver": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+ "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+ "dev": true
+ },
+ "shebang-command": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
+ "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=",
+ "dev": true,
+ "requires": {
+ "shebang-regex": "^1.0.0"
+ }
+ },
+ "shebang-regex": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz",
+ "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=",
+ "dev": true
+ },
+ "shell-quote": {
+ "version": "1.7.2",
+ "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.2.tgz",
+ "integrity": "sha512-mRz/m/JVscCrkMyPqHc/bczi3OQHkLTqXHEFu0zDhK/qfv3UcOA4SVmRCLmos4bhjr9ekVQubj/R7waKapmiQg==",
+ "dev": true
+ },
+ "side-channel": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",
+ "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.0",
+ "get-intrinsic": "^1.0.2",
+ "object-inspect": "^1.9.0"
+ }
+ },
+ "spdx-correct": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz",
+ "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==",
+ "dev": true,
+ "requires": {
+ "spdx-expression-parse": "^3.0.0",
+ "spdx-license-ids": "^3.0.0"
+ }
+ },
+ "spdx-exceptions": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz",
+ "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==",
+ "dev": true
+ },
+ "spdx-expression-parse": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz",
+ "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==",
+ "dev": true,
+ "requires": {
+ "spdx-exceptions": "^2.1.0",
+ "spdx-license-ids": "^3.0.0"
+ }
+ },
+ "spdx-license-ids": {
+ "version": "3.0.10",
+ "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.10.tgz",
+ "integrity": "sha512-oie3/+gKf7QtpitB0LYLETe+k8SifzsX4KixvpOsbI6S0kRiRQ5MKOio8eMSAKQ17N06+wdEOXRiId+zOxo0hA==",
+ "dev": true
+ },
+ "string.prototype.padend": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/string.prototype.padend/-/string.prototype.padend-3.1.2.tgz",
+ "integrity": "sha512-/AQFLdYvePENU3W5rgurfWSMU6n+Ww8n/3cUt7E+vPBB/D7YDG8x+qjoFs4M/alR2bW7Qg6xMjVwWUOvuQ0XpQ==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.3",
+ "es-abstract": "^1.18.0-next.2"
+ }
+ },
+ "string.prototype.trimend": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz",
+ "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.3"
+ }
+ },
+ "string.prototype.trimstart": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz",
+ "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.3"
+ }
+ },
+ "strip-bom": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
+ "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+ "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
+ },
+ "svelte": {
+ "version": "3.42.2",
+ "resolved": "https://registry.npmjs.org/svelte/-/svelte-3.42.2.tgz",
+ "integrity": "sha512-FOyNYKXb8wdE0Ot+Ctt2/OyDLsNBP8+V6PUE9ag6ZKeLslIou0LnMu1fhtWUA+HjzKTbAM1yj+4PFLtg/3pMJA==",
+ "dev": true
+ },
+ "unbox-primitive": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz",
+ "integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==",
+ "dev": true,
+ "requires": {
+ "function-bind": "^1.1.1",
+ "has-bigints": "^1.0.1",
+ "has-symbols": "^1.0.2",
+ "which-boxed-primitive": "^1.0.2"
+ }
+ },
+ "validate-npm-package-license": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz",
+ "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==",
+ "dev": true,
+ "requires": {
+ "spdx-correct": "^3.0.0",
+ "spdx-expression-parse": "^3.0.0"
+ }
+ },
+ "which": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
+ "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
+ "dev": true,
+ "requires": {
+ "isexe": "^2.0.0"
+ }
+ },
+ "which-boxed-primitive": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz",
+ "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==",
+ "dev": true,
+ "requires": {
+ "is-bigint": "^1.0.1",
+ "is-boolean-object": "^1.1.0",
+ "is-number-object": "^1.0.4",
+ "is-string": "^1.0.5",
+ "is-symbol": "^1.0.3"
+ }
+ }
+ }
+}
diff --git a/v2/internal/frontend/runtime/dev/package.json b/v2/internal/frontend/runtime/dev/package.json
new file mode 100644
index 000000000..a8fdade52
--- /dev/null
+++ b/v2/internal/frontend/runtime/dev/package.json
@@ -0,0 +1,18 @@
+{
+ "name": "dev",
+ "version": "2.0.0",
+ "description": "Wails JS Dev",
+ "main": "main.js",
+ "scripts": {
+ "build": "run-p build:*",
+ "build:dev": "node build.js"
+ },
+ "author": "Lea Anthony ",
+ "license": "ISC",
+ "devDependencies": {
+ "esbuild": "^0.12.17",
+ "npm-run-all": "^4.1.5",
+ "svelte": "^3.42.2",
+ "esbuild-svelte": "^0.5.6"
+ }
+}
diff --git a/v2/internal/frontend/runtime/dev/store.js b/v2/internal/frontend/runtime/dev/store.js
new file mode 100644
index 000000000..fc085570b
--- /dev/null
+++ b/v2/internal/frontend/runtime/dev/store.js
@@ -0,0 +1,12 @@
+import {writable} from 'svelte/store';
+
+/** Overlay */
+export const overlayVisible = writable(false);
+
+export function showOverlay() {
+ overlayVisible.set(true);
+}
+
+export function hideOverlay() {
+ overlayVisible.set(false);
+}
diff --git a/v2/internal/frontend/runtime/events.go b/v2/internal/frontend/runtime/events.go
new file mode 100644
index 000000000..d5a63855f
--- /dev/null
+++ b/v2/internal/frontend/runtime/events.go
@@ -0,0 +1,150 @@
+package runtime
+
+import (
+ "github.com/wailsapp/wails/v2/internal/frontend"
+ "github.com/wailsapp/wails/v2/internal/logger"
+ "sync"
+)
+
+// eventListener holds a callback function which is invoked when
+// the event listened for is emitted. It has a counter which indicates
+// how the total number of events it is interested in. A value of zero
+// means it does not expire (default).
+type eventListener struct {
+ callback func(...interface{}) // Function to call with emitted event data
+ counter int // The number of times this callback may be called. -1 = infinite
+ delete bool // Flag to indicate that this listener should be deleted
+}
+
+// Events handles eventing
+type Events struct {
+ log *logger.Logger
+ frontend []frontend.Frontend
+
+ // Go event listeners
+ listeners map[string][]*eventListener
+ notifyLock sync.RWMutex
+}
+
+func (e *Events) Notify(sender frontend.Frontend, name string, data ...interface{}) {
+ e.notifyBackend(name, data...)
+ for _, thisFrontend := range e.frontend {
+ if thisFrontend == sender {
+ continue
+ }
+ thisFrontend.Notify(name, data...)
+ }
+}
+
+func (e *Events) On(eventName string, callback func(...interface{})) {
+ e.registerListener(eventName, callback, -1)
+}
+
+func (e *Events) OnMultiple(eventName string, callback func(...interface{}), counter int) {
+ e.registerListener(eventName, callback, counter)
+}
+
+func (e *Events) Once(eventName string, callback func(...interface{})) {
+ e.registerListener(eventName, callback, 1)
+}
+
+func (e *Events) Emit(eventName string, data ...interface{}) {
+ e.notifyBackend(eventName, data...)
+ for _, thisFrontend := range e.frontend {
+ thisFrontend.Notify(eventName, data...)
+ }
+}
+
+func (e *Events) Off(eventName string) {
+ e.unRegisterListener(eventName)
+}
+
+// NewEvents creates a new log subsystem
+func NewEvents(log *logger.Logger) *Events {
+ result := &Events{
+ log: log,
+ listeners: make(map[string][]*eventListener),
+ }
+ return result
+}
+
+// registerListener provides a means of subscribing to events of type "eventName"
+func (e *Events) registerListener(eventName string, callback func(...interface{}), counter int) {
+ // Create new eventListener
+ thisListener := &eventListener{
+ callback: callback,
+ counter: counter,
+ delete: false,
+ }
+ e.notifyLock.Lock()
+ // Append the new listener to the listeners slice
+ e.listeners[eventName] = append(e.listeners[eventName], thisListener)
+ e.notifyLock.Unlock()
+}
+
+// unRegisterListener provides a means of unsubscribing to events of type "eventName"
+func (e *Events) unRegisterListener(eventName string) {
+ e.notifyLock.Lock()
+ // Clear the listeners
+ delete(e.listeners, eventName)
+ e.notifyLock.Unlock()
+}
+
+// Notify backend for the given event name
+func (e *Events) notifyBackend(eventName string, data ...interface{}) {
+
+ // Get list of event listeners
+ listeners := e.listeners[eventName]
+ if listeners == nil {
+ e.log.Trace("No listeners for event '%s'", eventName)
+ return
+ }
+
+ // Lock the listeners
+ e.notifyLock.Lock()
+
+ // We have a dirty flag to indicate that there are items to delete
+ itemsToDelete := false
+
+ // Callback in goroutine
+ for _, listener := range listeners {
+ if listener.counter > 0 {
+ listener.counter--
+ }
+ go listener.callback(data...)
+
+ if listener.counter == 0 {
+ listener.delete = true
+ itemsToDelete = true
+ }
+ }
+
+ // Do we have items to delete?
+ if itemsToDelete == true {
+
+ // Create a new Listeners slice
+ var newListeners []*eventListener
+
+ // Iterate over current listeners
+ for _, listener := range listeners {
+ // If we aren't deleting the listener, add it to the new list
+ if !listener.delete {
+ newListeners = append(newListeners, listener)
+ }
+ }
+
+ // Save new listeners or remove entry
+ if len(newListeners) > 0 {
+ e.listeners[eventName] = newListeners
+ } else {
+ delete(e.listeners, eventName)
+ }
+ }
+
+ // Unlock
+ e.notifyLock.Unlock()
+}
+
+func (e *Events) AddFrontend(appFrontend frontend.Frontend) {
+ e.frontend = append(e.frontend, appFrontend)
+}
diff --git a/v2/internal/frontend/runtime/ipc.go b/v2/internal/frontend/runtime/ipc.go
new file mode 100644
index 000000000..1f8873796
--- /dev/null
+++ b/v2/internal/frontend/runtime/ipc.go
@@ -0,0 +1,8 @@
+//go:build darwin || windows
+
+package runtime
+
+import _ "embed"
+
+//go:embed ipc.js
+var DesktopIPC []byte
diff --git a/v2/internal/frontend/runtime/ipc.js b/v2/internal/frontend/runtime/ipc.js
new file mode 100644
index 000000000..6947faa84
--- /dev/null
+++ b/v2/internal/frontend/runtime/ipc.js
@@ -0,0 +1 @@
+(()=>{(function(){let o=function(e){for(var s=window[e.shift()];s&&e.length;)s=s[e.shift()];return s},t=o(["chrome","webview","postMessage"]),n=o(["webkit","messageHandlers","external","postMessage"]);if(!t&&!n){console.error("Unsupported Platform");return}t&&(window.WailsInvoke=e=>window.chrome.webview.postMessage(e)),n&&(window.WailsInvoke=e=>window.webkit.messageHandlers.external.postMessage(e))})();})();
diff --git a/v2/internal/frontend/runtime/ipc_websocket.go b/v2/internal/frontend/runtime/ipc_websocket.go
new file mode 100644
index 000000000..e0b5ca1f2
--- /dev/null
+++ b/v2/internal/frontend/runtime/ipc_websocket.go
@@ -0,0 +1,8 @@
+//go:build dev
+
+package runtime
+
+import _ "embed"
+
+//go:embed ipc_websocket.js
+var WebsocketIPC []byte
diff --git a/v2/internal/frontend/runtime/ipc_websocket.js b/v2/internal/frontend/runtime/ipc_websocket.js
new file mode 100644
index 000000000..16774652b
--- /dev/null
+++ b/v2/internal/frontend/runtime/ipc_websocket.js
@@ -0,0 +1,22 @@
+(()=>{function F(t){console.log("%c wails dev %c "+t+" ","background: #aa0000; color: #fff; border-radius: 3px 0px 0px 3px; padding: 1px; font-size: 0.7rem","background: #009900; color: #fff; border-radius: 0px 3px 3px 0px; padding: 1px; font-size: 0.7rem")}function _(){}var j=t=>t;function G(t){return t()}function tt(){return Object.create(null)}function b(t){t.forEach(G)}function S(t){return typeof t=="function"}function O(t,e){return t!=t?e==e:t!==e||t&&typeof t=="object"||typeof t=="function"}function et(t){return Object.keys(t).length===0}function nt(t,...e){if(t==null)return _;let n=t.subscribe(...e);return n.unsubscribe?()=>n.unsubscribe():n}function it(t,e,n){t.$$.on_destroy.push(nt(e,n))}var ot=typeof window!="undefined",Et=ot?()=>window.performance.now():()=>Date.now(),q=ot?t=>requestAnimationFrame(t):_;var x=new Set;function rt(t){x.forEach(e=>{e.c(t)||(x.delete(e),e.f())}),x.size!==0&&q(rt)}function jt(t){let e;return x.size===0&&q(rt),{promise:new Promise(n=>{x.add(e={c:t,f:n})}),abort(){x.delete(e)}}}var st=!1;function Ot(){st=!0}function Dt(){st=!1}function At(t,e){t.appendChild(e)}function ct(t,e,n){let i=K(t);if(!i.getElementById(e)){let o=A("style");o.id=e,o.textContent=n,lt(i,o)}}function K(t){if(!t)return document;let e=t.getRootNode?t.getRootNode():t.ownerDocument;return e.host?e:document}function Lt(t){let e=A("style");return lt(K(t),e),e}function lt(t,e){At(t.head||t,e)}function P(t,e,n){t.insertBefore(e,n||null)}function D(t){t.parentNode.removeChild(t)}function A(t){return document.createElement(t)}function Bt(t){return document.createTextNode(t)}function ut(){return Bt("")}function at(t,e,n){n==null?t.removeAttribute(e):t.getAttribute(e)!==n&&t.setAttribute(e,n)}function Jt(t){return Array.from(t.childNodes)}function zt(t,e,n=!1){let i=document.createEvent("CustomEvent");return i.initCustomEvent(t,n,!1,e),i}var N=new Set,L=0;function Tt(t){let e=5381,n=t.length;for(;n--;)e=(e<<5)-e^t.charCodeAt(n);return e>>>0}function ft(t,e,n,i,o,c,s,l=0){let a=16.666/i,r=`{
+`;for(let g=0;g<=1;g+=a){let v=e+(n-e)*c(g);r+=g*100+`%{${s(v,1-v)}}
+`}let y=r+`100% {${s(n,1-n)}}
+}`,f=`__svelte_${Tt(y)}_${l}`,u=K(t);N.add(u);let h=u.__svelte_stylesheet||(u.__svelte_stylesheet=Lt(t).sheet),p=u.__svelte_rules||(u.__svelte_rules={});p[f]||(p[f]=!0,h.insertRule(`@keyframes ${f} ${y}`,h.cssRules.length));let w=t.style.animation||"";return t.style.animation=`${w?`${w}, `:""}${f} ${i}ms linear ${o}ms 1 both`,L+=1,f}function Ht(t,e){let n=(t.style.animation||"").split(", "),i=n.filter(e?c=>c.indexOf(e)<0:c=>c.indexOf("__svelte")===-1),o=n.length-i.length;o&&(t.style.animation=i.join(", "),L-=o,L||Gt())}function Gt(){q(()=>{L||(N.forEach(t=>{let e=t.__svelte_stylesheet,n=e.cssRules.length;for(;n--;)e.deleteRule(n);t.__svelte_rules={}}),N.clear())})}var dt;function B(t){dt=t}var k=[];var ht=[],J=[],pt=[],qt=Promise.resolve(),R=!1;function Kt(){R||(R=!0,qt.then(_t))}function M(t){J.push(t)}var W=!1,V=new Set;function _t(){if(!W){W=!0;do{for(let t=0;t{$=null})),$}function U(t,e,n){t.dispatchEvent(zt(`${e?"intro":"outro"}${n}`))}var z=new Set,m;function mt(){m={r:0,c:[],p:m}}function yt(){m.r||b(m.c),m=m.p}function I(t,e){t&&t.i&&(z.delete(t),t.i(e))}function X(t,e,n,i){if(t&&t.o){if(z.has(t))return;z.add(t),m.c.push(()=>{z.delete(t),i&&(n&&t.d(1),i())}),t.o(e)}}var Rt={duration:0};function Z(t,e,n,i){let o=e(t,n),c=i?0:1,s=null,l=null,a=null;function r(){a&&Ht(t,a)}function y(u,h){let p=u.b-c;return h*=Math.abs(p),{a:c,b:u.b,d:p,duration:h,start:u.start,end:u.start+h,group:u.group}}function f(u){let{delay:h=0,duration:p=300,easing:w=j,tick:g=_,css:v}=o||Rt,H={start:Et()+h,b:u};u||(H.group=m,m.r+=1),s||l?l=H:(v&&(r(),a=ft(t,c,u,p,h,w,v)),u&&g(0,1),s=y(H,p),M(()=>U(t,u,"start")),jt(E=>{if(l&&E>l.start&&(s=y(l,p),l=null,U(t,s.b,"start"),v&&(r(),a=ft(t,c,s.b,s.duration,0,w,o.css))),s){if(E>=s.end)g(c=s.b,1-c),U(t,s.b,"end"),l||(s.b?r():--s.group.r||b(s.group.c)),s=null;else if(E>=s.start){let It=E-s.start;c=s.a+s.d*w(It/s.duration),g(c,1-c)}}return!!(s||l)}))}return{run(u){S(o)?Nt().then(()=>{o=o(),f(u)}):f(u)},end(){r(),s=l=null}}}var re=typeof window!="undefined"?window:typeof globalThis!="undefined"?globalThis:global;var se=new Set(["allowfullscreen","allowpaymentrequest","async","autofocus","autoplay","checked","controls","default","defer","disabled","formnovalidate","hidden","ismap","loop","multiple","muted","nomodule","novalidate","open","playsinline","readonly","required","reversed","selected"]);function Wt(t,e,n,i){let{fragment:o,on_mount:c,on_destroy:s,after_update:l}=t.$$;o&&o.m(e,n),i||M(()=>{let a=c.map(G).filter(S);s?s.push(...a):b(a),t.$$.on_mount=[]}),l.forEach(M)}function gt(t,e){let n=t.$$;n.fragment!==null&&(b(n.on_destroy),n.fragment&&n.fragment.d(e),n.on_destroy=n.fragment=null,n.ctx=[])}function Vt(t,e){t.$$.dirty[0]===-1&&(k.push(t),Kt(),t.$$.dirty.fill(0)),t.$$.dirty[e/31|0]|=1<{let p=h.length?h[0]:u;return r.ctx&&o(r.ctx[f],r.ctx[f]=p)&&(!r.skip_bound&&r.bound[f]&&r.bound[f](p),y&&Vt(t,f)),u}):[],r.update(),y=!0,b(r.before_update),r.fragment=i?i(r.ctx):!1,e.target){if(e.hydrate){Ot();let f=Jt(e.target);r.fragment&&r.fragment.l(f),f.forEach(D)}else r.fragment&&r.fragment.c();e.intro&&I(t.$$.fragment),Wt(t,e.target,e.anchor,e.customElement),Dt(),_t()}B(a)}var Ut;typeof HTMLElement=="function"&&(Ut=class extends HTMLElement{constructor(){super();this.attachShadow({mode:"open"})}connectedCallback(){let{on_mount:t}=this.$$;this.$$.on_disconnect=t.map(G).filter(S);for(let e in this.$$.slotted)this.appendChild(this.$$.slotted[e])}attributeChangedCallback(t,e,n){this[t]=n}disconnectedCallback(){b(this.$$.on_disconnect)}$destroy(){gt(this,1),this.$destroy=_}$on(t,e){let n=this.$$.callbacks[t]||(this.$$.callbacks[t]=[]);return n.push(e),()=>{let i=n.indexOf(e);i!==-1&&n.splice(i,1)}}$set(t){this.$$set&&!et(t)&&(this.$$.skip_bound=!0,this.$$set(t),this.$$.skip_bound=!1)}});var Q=class{$destroy(){gt(this,1),this.$destroy=_}$on(e,n){let i=this.$$.callbacks[e]||(this.$$.callbacks[e]=[]);return i.push(n),()=>{let o=i.indexOf(n);o!==-1&&i.splice(o,1)}}$set(e){this.$$set&&!et(e)&&(this.$$.skip_bound=!0,this.$$set(e),this.$$.skip_bound=!1)}};var C=[];function wt(t,e=_){let n,i=new Set;function o(l){if(O(t,l)&&(t=l,n)){let a=!C.length;for(let r of i)r[1](),C.push(r,t);if(a){for(let r=0;r{i.delete(r),i.size===0&&(n(),n=null)}}return{set:o,update:c,subscribe:s}}var T=wt(!1);function vt(){T.set(!0)}function Ft(){T.set(!1)}function Y(t,{delay:e=0,duration:n=400,easing:i=j}={}){let o=+getComputedStyle(t).opacity;return{delay:e,duration:n,easing:i,css:c=>`opacity: ${c*o}`}}function Xt(t){ct(t,"svelte-181h7z",`.wails-reconnect-overlay.svelte-181h7z{position:fixed;top:0;left:0;width:100%;height:100%;backdrop-filter:blur(2px) saturate(0%) contrast(50%) brightness(25%);z-index:999999
+ }.wails-reconnect-overlay-content.svelte-181h7z{position:relative;top:50%;transform:translateY(-50%);margin:0;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEsAAAA7CAMAAAAEsocZAAAC91BMVEUAAACzQ0PjMjLkMjLZLS7XLS+vJCjkMjKlEx6uGyHjMDGiFx7GJyrAISjUKy3mMzPlMjLjMzOsGyDKJirkMjK6HyXmMjLgMDC6IiLcMjLULC3MJyrRKSy+IibmMzPmMjK7ISXlMjLIJimzHSLkMjKtGiHZLC7BIifgMDCpGSDFIivcLy+yHSKoGR+eFBzNKCvlMjKxHSPkMTKxHSLmMjLKJyq5ICXDJCe6ISXdLzDkMjLmMzPFJSm2HyTlMTLhMDGyHSKUEBmhFx24HyTCJCjHJijjMzOiFh7mMjJ6BhDaLDCuGyOKABjnMzPGJinJJiquHCGEChSmGB/pMzOiFh7VKy3OKCu1HiSvHCLjMTLMKCrBIyeICxWxHCLDIyjSKizBIyh+CBO9ISa6ISWDChS9Iie1HyXVLC7FJSrLKCrlMjLiMTGPDhicFRywGyKXFBuhFx1/BxO7IiXkMTGeFBx8BxLkMTGnGR/GJCi4ICWsGyGJDxXSLS2yGiHSKi3CJCfnMzPQKiyECRTKJiq6ISWUERq/Iye0HiPDJCjGJSm6ICaPDxiTEBrdLy+3HyXSKiy0HyOQEBi4ICWhFh1+CBO9IieODhfSKyzWLC2LDhh8BxHKKCq7ISWaFBzkMzPqNDTTLC3EJSiHDBacExyvGyO1HyTPKCy+IieoGSC7ISaVEhrMKCvQKyusGyG0HiKACBPIJSq/JCaABxR5BRLEJCnkMzPJJinEJimPDRZ2BRKqHx/jMjLnMzPgMDHULC3NKSvQKSzsNDTWLS7SKyy3HyTKJyrDJSjbLzDYLC6mGB/GJSnVLC61HiPLKCrHJSm/Iye8Iia6ICWzHSKxHCLaLi/PKSupGR+7ICXpMzPbLi/IJinJJSmsGyGrGiCkFx6PDheJCxaFChXBIyfAIieSDxmBCBPlMjLeLzDdLzC5HySMDRe+ISWvGyGcFBzSKSzPJyvMJyrEJCjDIyefFRyWERriMDHUKiy/ISaZExv0NjbwNTXuNDTrMzMI0c+yAAAAu3RSTlMAA8HR/gwGgAj+MEpGCsC+hGpjQjYnIxgWBfzx7urizMrFqqB1bF83KhsR/fz8+/r5+fXv7unZ1tC+t6mmopqKdW1nYVpVRjUeHhIQBPr59/b28/Hx8ODg3NvUw8O/vKeim5aNioiDgn1vZWNjX1xUU1JPTUVFPT08Mi4qJyIh/Pv7+/n4+Pf39fT08/Du7efn5uXj4uHa19XNwsG/vrq2tbSuramlnpyYkpGNiIZ+enRraGVjVVBKOzghdjzRsAAABJVJREFUWMPtllVQG1EYhTc0ASpoobS0FCulUHd3oUjd3d3d3d3d3d2b7CYhnkBCCHGDEIK7Vh56d0NpOgwkYfLQzvA9ZrLfnPvfc+8uVEst/yheBJup3Nya2MjU6pa/jWLZtxjXpZFtVB4uVNI6m5gIruNkVFebqIb5Ug2ym4TIEM/gtUOGbg613oBzjAzZFrZ+lXu/3TIiMXXS5M6HTvrNHeLpZLEh6suGNW9fzZ9zd/qVi2eOHygqi5cDE5GUrJocONgzyqo0UXNSUlKSEhMztFqtXq9vNxImAmS3g7Y6QlbjdBWVGW36jt4wDGTUXjUsafh5zJWRkdFuZGtWGnCRmg+HasiGMUClTTzW0ZuVgLlGDIPM4Lhi0IrVq+tv2hS21fNrSONQgpM9DsJ4t3fM9PkvJuKj2ZjrZwvILKvaSTgciUSirjt6dOfOpyd169bDb9rMOwF9Hj4OD100gY0YXYb299bjzMrqj9doNByJWlVXFB9DT5dmJuvy+cq83JyuS6ayEYSHulKL8dmFnBkrCeZlHKMrC5XRhXGCZB2Ty1fkleRQaMCFT2DBsEafzRFJu7/2MicbKynPhQUDLiZwMWLJZKNLzoLbJBYVcurSmbmn+rcyJ8vCMgmlmaW6gnwun/+3C96VpAUuET1ZgRR36r2xWlnYSnf3oKABA14uXDDvydxHs6cpTV1p3hlJ2rJCiUjIZCByItXg8sHJijuvT64CuMTABUYvb6NN1Jdp1PH7D7f3bo2eS5KvW4RJr7atWT5w4MBBg9zdBw9+37BS7QIoFS5WnIaj12dr1DEXFgdvr4fh4eFl+u/wz8uf3jjHic8s4DL2Dal0IANyUBeCRCcwOBJV26JsjSpGwHVuSai69jvqD+jr56OgtKy0zAAK5mLTVBKVKL5tNthGAR9JneJQ/bFsHNzy+U7IlCYROxtMpIjR0ceoQVnowracLLpAQWETqV361bPoFo3cEbz2zYLZM7t3HWXcxmiBOgttS1ycWkTXMWh4mGigdug9DFdttqCFgTN6nD0q1XEVSoCxEjyFCi2eNC6Z69MRVIImJ6JQSf5gcFVCuF+aDhCa1F6MJFDaiNBQAh2TMfWBjhmLsAxUjG/fmjs0qjJck8D0GPBcuUuZW1LS/tIsPzqmQt17PvZQknlwnf4tHDBc+7t5VV3QQCkdc+Ur8/hdrz0but0RCumWiYbiKmLJ7EVbRomj4Q7+y5wsaXvfTGFpQcHB7n2WbG4MGdniw2Tm8xl5Yhr7MrSYHQ3uampz10aWyHyuzxvqaW/6W4MjXAUD3QV2aw97ZxhGjxCohYf5TpTHMXU1BbsAuoFnkRygVieIGAbqiF7rrH4rfWpKJouBCtyHJF8ctEyGubBa+C6NsMYEUonJFITHZqWBxXUA12Dv76Tf/PgOBmeNiiLG1pcKo1HAq8jLpY4JU1yWEixVNaOgoRJAKBSZHTZTU+wJOMtUDZvlVITC6FTlksyrEBoPHXpxxbzdaqzigUtVDkJVIOtVQ9UEOR4VGUh/kHWq0edJ6CxnZ+eePXva2bnY/cF/I1RLLf8vvwDANdMSMegxcAAAAABJRU5ErkJggg==);background-repeat:no-repeat;background-position:center
+ }.wails-reconnect-overlay-loadingspinner.svelte-181h7z{pointer-events:none;width:2.5em;height:2.5em;border:.4em solid transparent;border-color:#f00 #eee0 #f00 #eee0;border-radius:50%;animation:svelte-181h7z-loadingspin 1s linear infinite;margin:auto;padding:2.5em
+ }@keyframes svelte-181h7z-loadingspin{100%{transform:rotate(360deg)}}`)}function xt(t){let e,n,i;return{c(){e=A("div"),e.innerHTML='',at(e,"class","wails-reconnect-overlay svelte-181h7z")},m(o,c){P(o,e,c),i=!0},i(o){i||(M(()=>{n||(n=Z(e,Y,{duration:300},!0)),n.run(1)}),i=!0)},o(o){n||(n=Z(e,Y,{duration:300},!1)),n.run(0),i=!1},d(o){o&&D(e),o&&n&&n.end()}}}function Zt(t){let e,n,i=t[0]&&xt(t);return{c(){i&&i.c(),e=ut()},m(o,c){i&&i.m(o,c),P(o,e,c),n=!0},p(o,[c]){o[0]?i?c&1&&I(i,1):(i=xt(o),i.c(),I(i,1),i.m(e.parentNode,e)):i&&(mt(),X(i,1,1,()=>{i=null}),yt())},i(o){n||(I(i),n=!0)},o(o){X(i),n=!1},d(o){i&&i.d(o),o&&D(e)}}}function Qt(t,e,n){let i;return it(t,T,o=>n(0,i=o)),[i]}var Mt=class extends Q{constructor(e){super();bt(this,e,Qt,Zt,O,{},Xt)}},Ct=Mt;var Yt={};window.ipcCallbacks=[];window.ipcCallbackNames=[];window.awaitIPC=(t,e)=>{if(!window.ipcCallbacks)return e;F("Queuing '"+t+"' for execution once ipc ready."),window.ipcCallbackNames.push(t),window.ipcCallbacks.push(e)};window.addEventListener("DOMContentLoaded",()=>{Yt.overlay=new Ct({target:document.body,anchor:document.querySelector("#wails-spinner")})});var d=null,St;window.onbeforeunload=function(){d&&(d.onclose=function(){},d.close(),d=null)};$t();function te(){window.WailsInvoke=t=>{d.send(t)};for(let t=0;t",
+ "license": "ISC",
+ "devDependencies": {
+ "esbuild": "^0.12.17",
+ "npm-run-all": "^4.1.5",
+ "svelte": "^3.42.2"
+ }
+}
diff --git a/v2/internal/frontend/runtime/runtime_dev_desktop.go b/v2/internal/frontend/runtime/runtime_dev_desktop.go
new file mode 100644
index 000000000..c0dcb1fc5
--- /dev/null
+++ b/v2/internal/frontend/runtime/runtime_dev_desktop.go
@@ -0,0 +1,8 @@
+//go:build dev || bindings || (!dev && !production && !bindings)
+
+package runtime
+
+import _ "embed"
+
+//go:embed runtime_dev_desktop.js
+var RuntimeDesktopJS []byte
diff --git a/v2/internal/frontend/runtime/runtime_dev_desktop.js b/v2/internal/frontend/runtime/runtime_dev_desktop.js
new file mode 100644
index 000000000..9106a51cf
--- /dev/null
+++ b/v2/internal/frontend/runtime/runtime_dev_desktop.js
@@ -0,0 +1,369 @@
+(() => {
+ var __defProp = Object.defineProperty;
+ var __markAsModule = (target) => __defProp(target, "__esModule", { value: true });
+ var __export = (target, all) => {
+ __markAsModule(target);
+ for (var name in all)
+ __defProp(target, name, { get: all[name], enumerable: true });
+ };
+
+ // desktop/log.js
+ var log_exports = {};
+ __export(log_exports, {
+ LogDebug: () => LogDebug,
+ LogError: () => LogError,
+ LogFatal: () => LogFatal,
+ LogInfo: () => LogInfo,
+ LogLevel: () => LogLevel,
+ LogPrint: () => LogPrint,
+ LogTrace: () => LogTrace,
+ LogWarning: () => LogWarning,
+ SetLogLevel: () => SetLogLevel
+ });
+ function sendLogMessage(level, message) {
+ window.WailsInvoke("L" + level + message);
+ }
+ function LogTrace(message) {
+ sendLogMessage("T", message);
+ }
+ function LogPrint(message) {
+ sendLogMessage("P", message);
+ }
+ function LogDebug(message) {
+ sendLogMessage("D", message);
+ }
+ function LogInfo(message) {
+ sendLogMessage("I", message);
+ }
+ function LogWarning(message) {
+ sendLogMessage("W", message);
+ }
+ function LogError(message) {
+ sendLogMessage("E", message);
+ }
+ function LogFatal(message) {
+ sendLogMessage("F", message);
+ }
+ function SetLogLevel(loglevel) {
+ sendLogMessage("S", loglevel);
+ }
+ var LogLevel = {
+ TRACE: 1,
+ DEBUG: 2,
+ INFO: 3,
+ WARNING: 4,
+ ERROR: 5
+ };
+
+ // desktop/events.js
+ var Listener = class {
+ constructor(callback, maxCallbacks) {
+ maxCallbacks = maxCallbacks || -1;
+ this.Callback = (data) => {
+ callback.apply(null, data);
+ if (maxCallbacks === -1) {
+ return false;
+ }
+ maxCallbacks -= 1;
+ return maxCallbacks === 0;
+ };
+ }
+ };
+ var eventListeners = {};
+ function EventsOnMultiple(eventName, callback, maxCallbacks) {
+ eventListeners[eventName] = eventListeners[eventName] || [];
+ const thisListener = new Listener(callback, maxCallbacks);
+ eventListeners[eventName].push(thisListener);
+ }
+ function EventsOn(eventName, callback) {
+ EventsOnMultiple(eventName, callback, -1);
+ }
+ function EventsOnce(eventName, callback) {
+ EventsOnMultiple(eventName, callback, 1);
+ }
+ function notifyListeners(eventData) {
+ let eventName = eventData.name;
+ if (eventListeners[eventName]) {
+ const newEventListenerList = eventListeners[eventName].slice();
+ for (let count = 0; count < eventListeners[eventName].length; count += 1) {
+ const listener = eventListeners[eventName][count];
+ let data = eventData.data;
+ const destroy = listener.Callback(data);
+ if (destroy) {
+ newEventListenerList.splice(count, 1);
+ }
+ }
+ eventListeners[eventName] = newEventListenerList;
+ }
+ }
+ function EventsNotify(notifyMessage) {
+ let message;
+ try {
+ message = JSON.parse(notifyMessage);
+ } catch (e) {
+ const error = "Invalid JSON passed to Notify: " + notifyMessage;
+ throw new Error(error);
+ }
+ notifyListeners(message);
+ }
+ function EventsEmit(eventName) {
+ const payload = {
+ name: eventName,
+ data: [].slice.apply(arguments).slice(1)
+ };
+ notifyListeners(payload);
+ window.WailsInvoke("EE" + JSON.stringify(payload));
+ }
+ function EventsOff(eventName) {
+ eventListeners.delete(eventName);
+ window.WailsInvoke("EX" + eventName);
+ }
+
+ // desktop/calls.js
+ var callbacks = {};
+ function cryptoRandom() {
+ var array = new Uint32Array(1);
+ return window.crypto.getRandomValues(array)[0];
+ }
+ function basicRandom() {
+ return Math.random() * 9007199254740991;
+ }
+ var randomFunc;
+ if (window.crypto) {
+ randomFunc = cryptoRandom;
+ } else {
+ randomFunc = basicRandom;
+ }
+ function Call(name, args, timeout) {
+ if (timeout == null) {
+ timeout = 0;
+ }
+ return new Promise(function(resolve, reject) {
+ var callbackID;
+ do {
+ callbackID = name + "-" + randomFunc();
+ } while (callbacks[callbackID]);
+ var timeoutHandle;
+ if (timeout > 0) {
+ timeoutHandle = setTimeout(function() {
+ reject(Error("Call to " + name + " timed out. Request ID: " + callbackID));
+ }, timeout);
+ }
+ callbacks[callbackID] = {
+ timeoutHandle,
+ reject,
+ resolve
+ };
+ try {
+ const payload = {
+ name,
+ args,
+ callbackID
+ };
+ window.WailsInvoke("C" + JSON.stringify(payload));
+ } catch (e) {
+ console.error(e);
+ }
+ });
+ }
+ function Callback(incomingMessage) {
+ var message;
+ try {
+ message = JSON.parse(incomingMessage);
+ } catch (e) {
+ const error = `Invalid JSON passed to callback: ${e.message}. Message: ${incomingMessage}`;
+ wails.LogDebug(error);
+ throw new Error(error);
+ }
+ var callbackID = message.callbackid;
+ var callbackData = callbacks[callbackID];
+ if (!callbackData) {
+ const error = `Callback '${callbackID}' not registered!!!`;
+ console.error(error);
+ throw new Error(error);
+ }
+ clearTimeout(callbackData.timeoutHandle);
+ delete callbacks[callbackID];
+ if (message.error) {
+ callbackData.reject(message.error);
+ } else {
+ callbackData.resolve(message.result);
+ }
+ }
+
+ // desktop/bindings.js
+ window.go = {};
+ function SetBindings(bindingsMap) {
+ try {
+ bindingsMap = JSON.parse(bindingsMap);
+ } catch (e) {
+ console.error(e);
+ }
+ window.go = window.go || {};
+ Object.keys(bindingsMap).forEach((packageName) => {
+ window.go[packageName] = window.go[packageName] || {};
+ Object.keys(bindingsMap[packageName]).forEach((structName) => {
+ window.go[packageName][structName] = window.go[packageName][structName] || {};
+ Object.keys(bindingsMap[packageName][structName]).forEach((methodName) => {
+ window.go[packageName][structName][methodName] = function() {
+ let timeout = 0;
+ function dynamic() {
+ const args = [].slice.call(arguments);
+ return Call([packageName, structName, methodName].join("."), args, timeout);
+ }
+ dynamic.setTimeout = function(newTimeout) {
+ timeout = newTimeout;
+ };
+ dynamic.getTimeout = function() {
+ return timeout;
+ };
+ return dynamic;
+ }();
+ });
+ });
+ });
+ }
+
+ // desktop/window.js
+ var window_exports = {};
+ __export(window_exports, {
+ WindowCenter: () => WindowCenter,
+ WindowFullscreen: () => WindowFullscreen,
+ WindowGetPosition: () => WindowGetPosition,
+ WindowGetSize: () => WindowGetSize,
+ WindowHide: () => WindowHide,
+ WindowMaximise: () => WindowMaximise,
+ WindowMinimise: () => WindowMinimise,
+ WindowReload: () => WindowReload,
+ WindowSetMaxSize: () => WindowSetMaxSize,
+ WindowSetMinSize: () => WindowSetMinSize,
+ WindowSetPosition: () => WindowSetPosition,
+ WindowSetRGBA: () => WindowSetRGBA,
+ WindowSetSize: () => WindowSetSize,
+ WindowSetTitle: () => WindowSetTitle,
+ WindowShow: () => WindowShow,
+ WindowUnFullscreen: () => WindowUnFullscreen,
+ WindowUnmaximise: () => WindowUnmaximise,
+ WindowUnminimise: () => WindowUnminimise
+ });
+ function WindowReload() {
+ window.location.reload();
+ }
+ function WindowCenter() {
+ window.WailsInvoke("Wc");
+ }
+ function WindowSetTitle(title) {
+ window.WailsInvoke("WT" + title);
+ }
+ function WindowFullscreen() {
+ window.WailsInvoke("WF");
+ }
+ function WindowUnFullscreen() {
+ window.WailsInvoke("Wf");
+ }
+ function WindowSetSize(width, height) {
+ window.WailsInvoke("Ws:" + width + ":" + height);
+ }
+ function WindowGetSize() {
+ return Call(":wails:WindowGetSize");
+ }
+ function WindowSetMaxSize(width, height) {
+ window.WailsInvoke("WZ:" + width + ":" + height);
+ }
+ function WindowSetMinSize(width, height) {
+ window.WailsInvoke("Wz:" + width + ":" + height);
+ }
+ function WindowSetPosition(x, y) {
+ window.WailsInvoke("Wp:" + x + ":" + y);
+ }
+ function WindowGetPosition() {
+ return Call(":wails:WindowGetPos");
+ }
+ function WindowHide() {
+ window.WailsInvoke("WH");
+ }
+ function WindowShow() {
+ window.WailsInvoke("WS");
+ }
+ function WindowMaximise() {
+ window.WailsInvoke("WM");
+ }
+ function WindowUnmaximise() {
+ window.WailsInvoke("WU");
+ }
+ function WindowMinimise() {
+ window.WailsInvoke("Wm");
+ }
+ function WindowUnminimise() {
+ window.WailsInvoke("Wu");
+ }
+ function WindowSetRGBA(RGBA) {
+ let rgba = JSON.stringify(RGBA);
+ window.WailsInvoke("Wr:" + rgba);
+ }
+
+ // desktop/browser.js
+ var browser_exports = {};
+ __export(browser_exports, {
+ BrowserOpenURL: () => BrowserOpenURL
+ });
+ function BrowserOpenURL(url) {
+ window.WailsInvoke("BO:" + url);
+ }
+
+ // desktop/main.js
+ function Quit() {
+ window.WailsInvoke("Q");
+ }
+ window.runtime = {
+ ...log_exports,
+ ...window_exports,
+ ...browser_exports,
+ EventsOn,
+ EventsOnce,
+ EventsOnMultiple,
+ EventsEmit,
+ EventsOff,
+ Quit
+ };
+ window.wails = {
+ Callback,
+ EventsNotify,
+ SetBindings,
+ eventListeners,
+ callbacks,
+ flags: {
+ disableScrollbarDrag: false,
+ disableWailsDefaultContextMenu: false
+ }
+ };
+ window.wails.SetBindings(window.wailsbindings);
+ delete window.wails.SetBindings;
+ if (true) {
+ delete window.wailsbindings;
+ }
+ window.addEventListener("mousedown", (e) => {
+ let currentElement = e.target;
+ while (currentElement != null) {
+ if (currentElement.hasAttribute("data-wails-no-drag")) {
+ break;
+ } else if (currentElement.hasAttribute("data-wails-drag")) {
+ if (window.wails.flags.disableScrollbarDrag) {
+ if (e.offsetX > e.target.clientWidth || e.offsetY > e.target.clientHeight) {
+ break;
+ }
+ }
+ window.WailsInvoke("drag");
+ e.preventDefault();
+ break;
+ }
+ currentElement = currentElement.parentElement;
+ }
+ });
+ window.addEventListener("contextmenu", function(e) {
+ if (window.wails.flags.disableWailsDefaultContextMenu) {
+ e.preventDefault();
+ }
+ });
+})();
+//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiZGVza3RvcC9sb2cuanMiLCAiZGVza3RvcC9ldmVudHMuanMiLCAiZGVza3RvcC9jYWxscy5qcyIsICJkZXNrdG9wL2JpbmRpbmdzLmpzIiwgImRlc2t0b3Avd2luZG93LmpzIiwgImRlc2t0b3AvYnJvd3Nlci5qcyIsICJkZXNrdG9wL21haW4uanMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbIi8qXG4gXyAgICAgICBfXyAgICAgIF8gX19cbnwgfCAgICAgLyAvX19fIF8oXykgL19fX19cbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cbnwgfC8gfC8gLyAvXy8gLyAvIChfXyAgKVxufF9fL3xfXy9cXF9fLF8vXy9fL19fX18vXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXG4oYykgTGVhIEFudGhvbnkgMjAxOS1wcmVzZW50XG4qL1xuXG4vKiBqc2hpbnQgZXN2ZXJzaW9uOiA2ICovXG5cbi8qKlxuICogU2VuZHMgYSBsb2cgbWVzc2FnZSB0byB0aGUgYmFja2VuZCB3aXRoIHRoZSBnaXZlbiBsZXZlbCArIG1lc3NhZ2VcbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gbGV2ZWxcbiAqIEBwYXJhbSB7c3RyaW5nfSBtZXNzYWdlXG4gKi9cbmZ1bmN0aW9uIHNlbmRMb2dNZXNzYWdlKGxldmVsLCBtZXNzYWdlKSB7XG5cblx0Ly8gTG9nIE1lc3NhZ2UgZm9ybWF0OlxuXHQvLyBsW3R5cGVdW21lc3NhZ2VdXG5cdHdpbmRvdy5XYWlsc0ludm9rZSgnTCcgKyBsZXZlbCArIG1lc3NhZ2UpO1xufVxuXG4vKipcbiAqIExvZyB0aGUgZ2l2ZW4gdHJhY2UgbWVzc2FnZSB3aXRoIHRoZSBiYWNrZW5kXG4gKlxuICogQGV4cG9ydFxuICogQHBhcmFtIHtzdHJpbmd9IG1lc3NhZ2VcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIExvZ1RyYWNlKG1lc3NhZ2UpIHtcblx0c2VuZExvZ01lc3NhZ2UoJ1QnLCBtZXNzYWdlKTtcbn1cblxuLyoqXG4gKiBMb2cgdGhlIGdpdmVuIG1lc3NhZ2Ugd2l0aCB0aGUgYmFja2VuZFxuICpcbiAqIEBleHBvcnRcbiAqIEBwYXJhbSB7c3RyaW5nfSBtZXNzYWdlXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBMb2dQcmludChtZXNzYWdlKSB7XG5cdHNlbmRMb2dNZXNzYWdlKCdQJywgbWVzc2FnZSk7XG59XG5cbi8qKlxuICogTG9nIHRoZSBnaXZlbiBkZWJ1ZyBtZXNzYWdlIHdpdGggdGhlIGJhY2tlbmRcbiAqXG4gKiBAZXhwb3J0XG4gKiBAcGFyYW0ge3N0cmluZ30gbWVzc2FnZVxuICovXG5leHBvcnQgZnVuY3Rpb24gTG9nRGVidWcobWVzc2FnZSkge1xuXHRzZW5kTG9nTWVzc2FnZSgnRCcsIG1lc3NhZ2UpO1xufVxuXG4vKipcbiAqIExvZyB0aGUgZ2l2ZW4gaW5mbyBtZXNzYWdlIHdpdGggdGhlIGJhY2tlbmRcbiAqXG4gKiBAZXhwb3J0XG4gKiBAcGFyYW0ge3N0cmluZ30gbWVzc2FnZVxuICovXG5leHBvcnQgZnVuY3Rpb24gTG9nSW5mbyhtZXNzYWdlKSB7XG5cdHNlbmRMb2dNZXNzYWdlKCdJJywgbWVzc2FnZSk7XG59XG5cbi8qKlxuICogTG9nIHRoZSBnaXZlbiB3YXJuaW5nIG1lc3NhZ2Ugd2l0aCB0aGUgYmFja2VuZFxuICpcbiAqIEBleHBvcnRcbiAqIEBwYXJhbSB7c3RyaW5nfSBtZXNzYWdlXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBMb2dXYXJuaW5nKG1lc3NhZ2UpIHtcblx0c2VuZExvZ01lc3NhZ2UoJ1cnLCBtZXNzYWdlKTtcbn1cblxuLyoqXG4gKiBMb2cgdGhlIGdpdmVuIGVycm9yIG1lc3NhZ2Ugd2l0aCB0aGUgYmFja2VuZFxuICpcbiAqIEBleHBvcnRcbiAqIEBwYXJhbSB7c3RyaW5nfSBtZXNzYWdlXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBMb2dFcnJvcihtZXNzYWdlKSB7XG5cdHNlbmRMb2dNZXNzYWdlKCdFJywgbWVzc2FnZSk7XG59XG5cbi8qKlxuICogTG9nIHRoZSBnaXZlbiBmYXRhbCBtZXNzYWdlIHdpdGggdGhlIGJhY2tlbmRcbiAqXG4gKiBAZXhwb3J0XG4gKiBAcGFyYW0ge3N0cmluZ30gbWVzc2FnZVxuICovXG5leHBvcnQgZnVuY3Rpb24gTG9nRmF0YWwobWVzc2FnZSkge1xuXHRzZW5kTG9nTWVzc2FnZSgnRicsIG1lc3NhZ2UpO1xufVxuXG4vKipcbiAqIFNldHMgdGhlIExvZyBsZXZlbCB0byB0aGUgZ2l2ZW4gbG9nIGxldmVsXG4gKlxuICogQGV4cG9ydFxuICogQHBhcmFtIHtudW1iZXJ9IGxvZ2xldmVsXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBTZXRMb2dMZXZlbChsb2dsZXZlbCkge1xuXHRzZW5kTG9nTWVzc2FnZSgnUycsIGxvZ2xldmVsKTtcbn1cblxuLy8gTG9nIGxldmVsc1xuZXhwb3J0IGNvbnN0IExvZ0xldmVsID0ge1xuXHRUUkFDRTogMSxcblx0REVCVUc6IDIsXG5cdElORk86IDMsXG5cdFdBUk5JTkc6IDQsXG5cdEVSUk9SOiA1LFxufTtcbiIsICIvKlxuIF8gICAgICAgX18gICAgICBfIF9fXG58IHwgICAgIC8gL19fXyBfKF8pIC9fX19fXG58IHwgL3wgLyAvIF9fIGAvIC8gLyBfX18vXG58IHwvIHwvIC8gL18vIC8gLyAoX18gIClcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xuVGhlIGVsZWN0cm9uIGFsdGVybmF0aXZlIGZvciBHb1xuKGMpIExlYSBBbnRob255IDIwMTktcHJlc2VudFxuKi9cbi8qIGpzaGludCBlc3ZlcnNpb246IDYgKi9cblxuLy8gRGVmaW5lcyBhIHNpbmdsZSBsaXN0ZW5lciB3aXRoIGEgbWF4aW11bSBudW1iZXIgb2YgdGltZXMgdG8gY2FsbGJhY2tcblxuLyoqXG4gKiBUaGUgTGlzdGVuZXIgY2xhc3MgZGVmaW5lcyBhIGxpc3RlbmVyISA6LSlcbiAqXG4gKiBAY2xhc3MgTGlzdGVuZXJcbiAqL1xuY2xhc3MgTGlzdGVuZXIge1xuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYW4gaW5zdGFuY2Ugb2YgTGlzdGVuZXIuXG4gICAgICogQHBhcmFtIHtmdW5jdGlvbn0gY2FsbGJhY2tcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gbWF4Q2FsbGJhY2tzXG4gICAgICogQG1lbWJlcm9mIExpc3RlbmVyXG4gICAgICovXG4gICAgY29uc3RydWN0b3IoY2FsbGJhY2ssIG1heENhbGxiYWNrcykge1xuICAgICAgICAvLyBEZWZhdWx0IG9mIC0xIG1lYW5zIGluZmluaXRlXG4gICAgICAgIG1heENhbGxiYWNrcyA9IG1heENhbGxiYWNrcyB8fCAtMTtcbiAgICAgICAgLy8gQ2FsbGJhY2sgaW52b2tlcyB0aGUgY2FsbGJhY2sgd2l0aCB0aGUgZ2l2ZW4gZGF0YVxuICAgICAgICAvLyBSZXR1cm5zIHRydWUgaWYgdGhpcyBsaXN0ZW5lciBzaG91bGQgYmUgZGVzdHJveWVkXG4gICAgICAgIHRoaXMuQ2FsbGJhY2sgPSAoZGF0YSkgPT4ge1xuICAgICAgICAgICAgY2FsbGJhY2suYXBwbHkobnVsbCwgZGF0YSk7XG4gICAgICAgICAgICAvLyBJZiBtYXhDYWxsYmFja3MgaXMgaW5maW5pdGUsIHJldHVybiBmYWxzZSAoZG8gbm90IGRlc3Ryb3kpXG4gICAgICAgICAgICBpZiAobWF4Q2FsbGJhY2tzID09PSAtMSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIERlY3JlbWVudCBtYXhDYWxsYmFja3MuIFJldHVybiB0cnVlIGlmIG5vdyAwLCBvdGhlcndpc2UgZmFsc2VcbiAgICAgICAgICAgIG1heENhbGxiYWNrcyAtPSAxO1xuICAgICAgICAgICAgcmV0dXJuIG1heENhbGxiYWNrcyA9PT0gMDtcbiAgICAgICAgfTtcbiAgICB9XG59XG5cbmV4cG9ydCBjb25zdCBldmVudExpc3RlbmVycyA9IHt9O1xuXG4vKipcbiAqIFJlZ2lzdGVycyBhbiBldmVudCBsaXN0ZW5lciB0aGF0IHdpbGwgYmUgaW52b2tlZCBgbWF4Q2FsbGJhY2tzYCB0aW1lcyBiZWZvcmUgYmVpbmcgZGVzdHJveWVkXG4gKlxuICogQGV4cG9ydFxuICogQHBhcmFtIHtzdHJpbmd9IGV2ZW50TmFtZVxuICogQHBhcmFtIHtmdW5jdGlvbn0gY2FsbGJhY2tcbiAqIEBwYXJhbSB7bnVtYmVyfSBtYXhDYWxsYmFja3NcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIEV2ZW50c09uTXVsdGlwbGUoZXZlbnROYW1lLCBjYWxsYmFjaywgbWF4Q2FsbGJhY2tzKSB7XG4gICAgZXZlbnRMaXN0ZW5lcnNbZXZlbnROYW1lXSA9IGV2ZW50TGlzdGVuZXJzW2V2ZW50TmFtZV0gfHwgW107XG4gICAgY29uc3QgdGhpc0xpc3RlbmVyID0gbmV3IExpc3RlbmVyKGNhbGxiYWNrLCBtYXhDYWxsYmFja3MpO1xuICAgIGV2ZW50TGlzdGVuZXJzW2V2ZW50TmFtZV0ucHVzaCh0aGlzTGlzdGVuZXIpO1xufVxuXG4vKipcbiAqIFJlZ2lzdGVycyBhbiBldmVudCBsaXN0ZW5lciB0aGF0IHdpbGwgYmUgaW52b2tlZCBldmVyeSB0aW1lIHRoZSBldmVudCBpcyBlbWl0dGVkXG4gKlxuICogQGV4cG9ydFxuICogQHBhcmFtIHtzdHJpbmd9IGV2ZW50TmFtZVxuICogQHBhcmFtIHtmdW5jdGlvbn0gY2FsbGJhY2tcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIEV2ZW50c09uKGV2ZW50TmFtZSwgY2FsbGJhY2spIHtcbiAgICBFdmVudHNPbk11bHRpcGxlKGV2ZW50TmFtZSwgY2FsbGJhY2ssIC0xKTtcbn1cblxuLyoqXG4gKiBSZWdpc3RlcnMgYW4gZXZlbnQgbGlzdGVuZXIgdGhhdCB3aWxsIGJlIGludm9rZWQgb25jZSB0aGVuIGRlc3Ryb3llZFxuICpcbiAqIEBleHBvcnRcbiAqIEBwYXJhbSB7c3RyaW5nfSBldmVudE5hbWVcbiAqIEBwYXJhbSB7ZnVuY3Rpb259IGNhbGxiYWNrXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBFdmVudHNPbmNlKGV2ZW50TmFtZSwgY2FsbGJhY2spIHtcbiAgICBFdmVudHNPbk11bHRpcGxlKGV2ZW50TmFtZSwgY2FsbGJhY2ssIDEpO1xufVxuXG5mdW5jdGlvbiBub3RpZnlMaXN0ZW5lcnMoZXZlbnREYXRhKSB7XG5cbiAgICAvLyBHZXQgdGhlIGV2ZW50IG5hbWVcbiAgICBsZXQgZXZlbnROYW1lID0gZXZlbnREYXRhLm5hbWU7XG5cbiAgICAvLyBDaGVjayBpZiB3ZSBoYXZlIGFueSBsaXN0ZW5lcnMgZm9yIHRoaXMgZXZlbnRcbiAgICBpZiAoZXZlbnRMaXN0ZW5lcnNbZXZlbnROYW1lXSkge1xuXG4gICAgICAgIC8vIEtlZXAgYSBsaXN0IG9mIGxpc3RlbmVyIGluZGV4ZXMgdG8gZGVzdHJveVxuICAgICAgICBjb25zdCBuZXdFdmVudExpc3RlbmVyTGlzdCA9IGV2ZW50TGlzdGVuZXJzW2V2ZW50TmFtZV0uc2xpY2UoKTtcblxuICAgICAgICAvLyBJdGVyYXRlIGxpc3RlbmVyc1xuICAgICAgICBmb3IgKGxldCBjb3VudCA9IDA7IGNvdW50IDwgZXZlbnRMaXN0ZW5lcnNbZXZlbnROYW1lXS5sZW5ndGg7IGNvdW50ICs9IDEpIHtcblxuICAgICAgICAgICAgLy8gR2V0IG5leHQgbGlzdGVuZXJcbiAgICAgICAgICAgIGNvbnN0IGxpc3RlbmVyID0gZXZlbnRMaXN0ZW5lcnNbZXZlbnROYW1lXVtjb3VudF07XG5cbiAgICAgICAgICAgIGxldCBkYXRhID0gZXZlbnREYXRhLmRhdGE7XG5cbiAgICAgICAgICAgIC8vIERvIHRoZSBjYWxsYmFja1xuICAgICAgICAgICAgY29uc3QgZGVzdHJveSA9IGxpc3RlbmVyLkNhbGxiYWNrKGRhdGEpO1xuICAgICAgICAgICAgaWYgKGRlc3Ryb3kpIHtcbiAgICAgICAgICAgICAgICAvLyBpZiB0aGUgbGlzdGVuZXIgaW5kaWNhdGVkIHRvIGRlc3Ryb3kgaXRzZWxmLCBhZGQgaXQgdG8gdGhlIGRlc3Ryb3kgbGlzdFxuICAgICAgICAgICAgICAgIG5ld0V2ZW50TGlzdGVuZXJMaXN0LnNwbGljZShjb3VudCwgMSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyBVcGRhdGUgY2FsbGJhY2tzIHdpdGggbmV3IGxpc3Qgb2YgbGlzdGVuZXJzXG4gICAgICAgIGV2ZW50TGlzdGVuZXJzW2V2ZW50TmFtZV0gPSBuZXdFdmVudExpc3RlbmVyTGlzdDtcbiAgICB9XG59XG5cbi8qKlxuICogTm90aWZ5IGluZm9ybXMgZnJvbnRlbmQgbGlzdGVuZXJzIHRoYXQgYW4gZXZlbnQgd2FzIGVtaXR0ZWQgd2l0aCB0aGUgZ2l2ZW4gZGF0YVxuICpcbiAqIEBleHBvcnRcbiAqIEBwYXJhbSB7c3RyaW5nfSBub3RpZnlNZXNzYWdlIC0gZW5jb2RlZCBub3RpZmljYXRpb24gbWVzc2FnZVxuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBFdmVudHNOb3RpZnkobm90aWZ5TWVzc2FnZSkge1xuICAgIC8vIFBhcnNlIHRoZSBtZXNzYWdlXG4gICAgbGV0IG1lc3NhZ2U7XG4gICAgdHJ5IHtcbiAgICAgICAgbWVzc2FnZSA9IEpTT04ucGFyc2Uobm90aWZ5TWVzc2FnZSk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgICBjb25zdCBlcnJvciA9ICdJbnZhbGlkIEpTT04gcGFzc2VkIHRvIE5vdGlmeTogJyArIG5vdGlmeU1lc3NhZ2U7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihlcnJvcik7XG4gICAgfVxuICAgIG5vdGlmeUxpc3RlbmVycyhtZXNzYWdlKTtcbn1cblxuLyoqXG4gKiBFbWl0IGFuIGV2ZW50IHdpdGggdGhlIGdpdmVuIG5hbWUgYW5kIGRhdGFcbiAqXG4gKiBAZXhwb3J0XG4gKiBAcGFyYW0ge3N0cmluZ30gZXZlbnROYW1lXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBFdmVudHNFbWl0KGV2ZW50TmFtZSkge1xuXG4gICAgY29uc3QgcGF5bG9hZCA9IHtcbiAgICAgICAgbmFtZTogZXZlbnROYW1lLFxuICAgICAgICBkYXRhOiBbXS5zbGljZS5hcHBseShhcmd1bWVudHMpLnNsaWNlKDEpLFxuICAgIH07XG5cbiAgICAvLyBOb3RpZnkgSlMgbGlzdGVuZXJzXG4gICAgbm90aWZ5TGlzdGVuZXJzKHBheWxvYWQpO1xuXG4gICAgLy8gTm90aWZ5IEdvIGxpc3RlbmVyc1xuICAgIHdpbmRvdy5XYWlsc0ludm9rZSgnRUUnICsgSlNPTi5zdHJpbmdpZnkocGF5bG9hZCkpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gRXZlbnRzT2ZmKGV2ZW50TmFtZSkge1xuICAgIC8vIFJlbW92ZSBsb2NhbCBsaXN0ZW5lcnNcbiAgICBldmVudExpc3RlbmVycy5kZWxldGUoZXZlbnROYW1lKTtcblxuICAgIC8vIE5vdGlmeSBHbyBsaXN0ZW5lcnNcbiAgICB3aW5kb3cuV2FpbHNJbnZva2UoJ0VYJyArIGV2ZW50TmFtZSk7XG59IiwgIi8qXG4gXyAgICAgICBfXyAgICAgIF8gX19cbnwgfCAgICAgLyAvX19fIF8oXykgL19fX19cbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cbnwgfC8gfC8gLyAvXy8gLyAvIChfXyAgKVxufF9fL3xfXy9cXF9fLF8vXy9fL19fX18vXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXG4oYykgTGVhIEFudGhvbnkgMjAxOS1wcmVzZW50XG4qL1xuLyoganNoaW50IGVzdmVyc2lvbjogNiAqL1xuXG5leHBvcnQgY29uc3QgY2FsbGJhY2tzID0ge307XG5cbi8qKlxuICogUmV0dXJucyBhIG51bWJlciBmcm9tIHRoZSBuYXRpdmUgYnJvd3NlciByYW5kb20gZnVuY3Rpb25cbiAqXG4gKiBAcmV0dXJucyBudW1iZXJcbiAqL1xuZnVuY3Rpb24gY3J5cHRvUmFuZG9tKCkge1xuXHR2YXIgYXJyYXkgPSBuZXcgVWludDMyQXJyYXkoMSk7XG5cdHJldHVybiB3aW5kb3cuY3J5cHRvLmdldFJhbmRvbVZhbHVlcyhhcnJheSlbMF07XG59XG5cbi8qKlxuICogUmV0dXJucyBhIG51bWJlciB1c2luZyBkYSBvbGQtc2tvb2wgTWF0aC5SYW5kb21cbiAqIEkgbGlrZXMgdG8gY2FsbCBpdCBMT0xSYW5kb21cbiAqXG4gKiBAcmV0dXJucyBudW1iZXJcbiAqL1xuZnVuY3Rpb24gYmFzaWNSYW5kb20oKSB7XG5cdHJldHVybiBNYXRoLnJhbmRvbSgpICogOTAwNzE5OTI1NDc0MDk5MTtcbn1cblxuLy8gUGljayBhIHJhbmRvbSBudW1iZXIgZnVuY3Rpb24gYmFzZWQgb24gYnJvd3NlciBjYXBhYmlsaXR5XG52YXIgcmFuZG9tRnVuYztcbmlmICh3aW5kb3cuY3J5cHRvKSB7XG5cdHJhbmRvbUZ1bmMgPSBjcnlwdG9SYW5kb207XG59IGVsc2Uge1xuXHRyYW5kb21GdW5jID0gYmFzaWNSYW5kb207XG59XG5cblxuLyoqXG4gKiBDYWxsIHNlbmRzIGEgbWVzc2FnZSB0byB0aGUgYmFja2VuZCB0byBjYWxsIHRoZSBiaW5kaW5nIHdpdGggdGhlXG4gKiBnaXZlbiBkYXRhLiBBIHByb21pc2UgaXMgcmV0dXJuZWQgYW5kIHdpbGwgYmUgY29tcGxldGVkIHdoZW4gdGhlXG4gKiBiYWNrZW5kIHJlc3BvbmRzLiBUaGlzIHdpbGwgYmUgcmVzb2x2ZWQgd2hlbiB0aGUgY2FsbCB3YXMgc3VjY2Vzc2Z1bFxuICogb3IgcmVqZWN0ZWQgaWYgYW4gZXJyb3IgaXMgcGFzc2VkIGJhY2suXG4gKiBUaGVyZSBpcyBhIHRpbWVvdXQgbWVjaGFuaXNtLiBJZiB0aGUgY2FsbCBkb2Vzbid0IHJlc3BvbmQgaW4gdGhlIGdpdmVuXG4gKiB0aW1lIChpbiBtaWxsaXNlY29uZHMpIHRoZW4gdGhlIHByb21pc2UgaXMgcmVqZWN0ZWQuXG4gKlxuICogQGV4cG9ydFxuICogQHBhcmFtIHtzdHJpbmd9IG5hbWVcbiAqIEBwYXJhbSB7YW55PX0gYXJnc1xuICogQHBhcmFtIHtudW1iZXI9fSB0aW1lb3V0XG4gKiBAcmV0dXJuc1xuICovXG5leHBvcnQgZnVuY3Rpb24gQ2FsbChuYW1lLCBhcmdzLCB0aW1lb3V0KSB7XG5cblx0Ly8gVGltZW91dCBpbmZpbml0ZSBieSBkZWZhdWx0XG5cdGlmICh0aW1lb3V0ID09IG51bGwpIHtcblx0XHR0aW1lb3V0ID0gMDtcblx0fVxuXG5cdC8vIENyZWF0ZSBhIHByb21pc2Vcblx0cmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHtcblxuXHRcdC8vIENyZWF0ZSBhIHVuaXF1ZSBjYWxsYmFja0lEXG5cdFx0dmFyIGNhbGxiYWNrSUQ7XG5cdFx0ZG8ge1xuXHRcdFx0Y2FsbGJhY2tJRCA9IG5hbWUgKyAnLScgKyByYW5kb21GdW5jKCk7XG5cdFx0fSB3aGlsZSAoY2FsbGJhY2tzW2NhbGxiYWNrSURdKTtcblxuXHRcdHZhciB0aW1lb3V0SGFuZGxlO1xuXHRcdC8vIFNldCB0aW1lb3V0XG5cdFx0aWYgKHRpbWVvdXQgPiAwKSB7XG5cdFx0XHR0aW1lb3V0SGFuZGxlID0gc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG5cdFx0XHRcdHJlamVjdChFcnJvcignQ2FsbCB0byAnICsgbmFtZSArICcgdGltZWQgb3V0LiBSZXF1ZXN0IElEOiAnICsgY2FsbGJhY2tJRCkpO1xuXHRcdFx0fSwgdGltZW91dCk7XG5cdFx0fVxuXG5cdFx0Ly8gU3RvcmUgY2FsbGJhY2tcblx0XHRjYWxsYmFja3NbY2FsbGJhY2tJRF0gPSB7XG5cdFx0XHR0aW1lb3V0SGFuZGxlOiB0aW1lb3V0SGFuZGxlLFxuXHRcdFx0cmVqZWN0OiByZWplY3QsXG5cdFx0XHRyZXNvbHZlOiByZXNvbHZlXG5cdFx0fTtcblxuXHRcdHRyeSB7XG5cdFx0XHRjb25zdCBwYXlsb2FkID0ge1xuXHRcdFx0XHRuYW1lLFxuXHRcdFx0XHRhcmdzLFxuXHRcdFx0XHRjYWxsYmFja0lELFxuXHRcdFx0fTtcblxuXHRcdFx0Ly8gTWFrZSB0aGUgY2FsbFxuXHRcdFx0d2luZG93LldhaWxzSW52b2tlKCdDJyArIEpTT04uc3RyaW5naWZ5KHBheWxvYWQpKTtcblx0XHR9IGNhdGNoIChlKSB7XG5cdFx0XHQvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmVcblx0XHRcdGNvbnNvbGUuZXJyb3IoZSk7XG5cdFx0fVxuXHR9KTtcbn1cblxuXG5cbi8qKlxuICogQ2FsbGVkIGJ5IHRoZSBiYWNrZW5kIHRvIHJldHVybiBkYXRhIHRvIGEgcHJldmlvdXNseSBjYWxsZWRcbiAqIGJpbmRpbmcgaW52b2NhdGlvblxuICpcbiAqIEBleHBvcnRcbiAqIEBwYXJhbSB7c3RyaW5nfSBpbmNvbWluZ01lc3NhZ2VcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIENhbGxiYWNrKGluY29taW5nTWVzc2FnZSkge1xuXHQvLyBEZWNvZGUgdGhlIG1lc3NhZ2UgLSBDcmVkaXQ6IGh0dHBzOi8vc3RhY2tvdmVyZmxvdy5jb20vYS8xMzg2NTY4MFxuXHQvL2luY29taW5nTWVzc2FnZSA9IGRlY29kZVVSSUNvbXBvbmVudChpbmNvbWluZ01lc3NhZ2UucmVwbGFjZSgvXFxzKy9nLCAnJykucmVwbGFjZSgvWzAtOWEtZl17Mn0vZywgJyUkJicpKTtcblxuXHQvLyBQYXJzZSB0aGUgbWVzc2FnZVxuXHR2YXIgbWVzc2FnZTtcblx0dHJ5IHtcblx0XHRtZXNzYWdlID0gSlNPTi5wYXJzZShpbmNvbWluZ01lc3NhZ2UpO1xuXHR9IGNhdGNoIChlKSB7XG5cdFx0Y29uc3QgZXJyb3IgPSBgSW52YWxpZCBKU09OIHBhc3NlZCB0byBjYWxsYmFjazogJHtlLm1lc3NhZ2V9LiBNZXNzYWdlOiAke2luY29taW5nTWVzc2FnZX1gO1xuXHRcdHdhaWxzLkxvZ0RlYnVnKGVycm9yKTtcblx0XHR0aHJvdyBuZXcgRXJyb3IoZXJyb3IpO1xuXHR9XG5cdHZhciBjYWxsYmFja0lEID0gbWVzc2FnZS5jYWxsYmFja2lkO1xuXHR2YXIgY2FsbGJhY2tEYXRhID0gY2FsbGJhY2tzW2NhbGxiYWNrSURdO1xuXHRpZiAoIWNhbGxiYWNrRGF0YSkge1xuXHRcdGNvbnN0IGVycm9yID0gYENhbGxiYWNrICcke2NhbGxiYWNrSUR9JyBub3QgcmVnaXN0ZXJlZCEhIWA7XG5cdFx0Y29uc29sZS5lcnJvcihlcnJvcik7IC8vIGVzbGludC1kaXNhYmxlLWxpbmVcblx0XHR0aHJvdyBuZXcgRXJyb3IoZXJyb3IpO1xuXHR9XG5cdGNsZWFyVGltZW91dChjYWxsYmFja0RhdGEudGltZW91dEhhbmRsZSk7XG5cblx0ZGVsZXRlIGNhbGxiYWNrc1tjYWxsYmFja0lEXTtcblxuXHRpZiAobWVzc2FnZS5lcnJvcikge1xuXHRcdGNhbGxiYWNrRGF0YS5yZWplY3QobWVzc2FnZS5lcnJvcik7XG5cdH0gZWxzZSB7XG5cdFx0Y2FsbGJhY2tEYXRhLnJlc29sdmUobWVzc2FnZS5yZXN1bHQpO1xuXHR9XG59XG4iLCAiLypcbiBfICAgICAgIF9fICAgICAgXyBfXyAgICBcbnwgfCAgICAgLyAvX19fIF8oXykgL19fX19cbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cbnwgfC8gfC8gLyAvXy8gLyAvIChfXyAgKSBcbnxfXy98X18vXFxfXyxfL18vXy9fX19fLyAgXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXG4oYykgTGVhIEFudGhvbnkgMjAxOS1wcmVzZW50XG4qL1xuLyoganNoaW50IGVzdmVyc2lvbjogNiAqL1xuXG5pbXBvcnQge0NhbGx9IGZyb20gJy4vY2FsbHMnO1xuXG4vLyBUaGlzIGlzIHdoZXJlIHdlIGJpbmQgZ28gbWV0aG9kIHdyYXBwZXJzXG53aW5kb3cuZ28gPSB7fTtcblxuZXhwb3J0IGZ1bmN0aW9uIFNldEJpbmRpbmdzKGJpbmRpbmdzTWFwKSB7XG5cdHRyeSB7XG5cdFx0YmluZGluZ3NNYXAgPSBKU09OLnBhcnNlKGJpbmRpbmdzTWFwKTtcblx0fSBjYXRjaCAoZSkge1xuXHRcdGNvbnNvbGUuZXJyb3IoZSk7XG5cdH1cblxuXHQvLyBJbml0aWFsaXNlIHRoZSBiaW5kaW5ncyBtYXBcblx0d2luZG93LmdvID0gd2luZG93LmdvIHx8IHt9O1xuXG5cdC8vIEl0ZXJhdGUgcGFja2FnZSBuYW1lc1xuXHRPYmplY3Qua2V5cyhiaW5kaW5nc01hcCkuZm9yRWFjaCgocGFja2FnZU5hbWUpID0+IHtcblxuXHRcdC8vIENyZWF0ZSBpbm5lciBtYXAgaWYgaXQgZG9lc24ndCBleGlzdFxuXHRcdHdpbmRvdy5nb1twYWNrYWdlTmFtZV0gPSB3aW5kb3cuZ29bcGFja2FnZU5hbWVdIHx8IHt9O1xuXG5cdFx0Ly8gSXRlcmF0ZSBzdHJ1Y3QgbmFtZXNcblx0XHRPYmplY3Qua2V5cyhiaW5kaW5nc01hcFtwYWNrYWdlTmFtZV0pLmZvckVhY2goKHN0cnVjdE5hbWUpID0+IHtcblxuXHRcdFx0Ly8gQ3JlYXRlIGlubmVyIG1hcCBpZiBpdCBkb2Vzbid0IGV4aXN0XG5cdFx0XHR3aW5kb3cuZ29bcGFja2FnZU5hbWVdW3N0cnVjdE5hbWVdID0gd2luZG93LmdvW3BhY2thZ2VOYW1lXVtzdHJ1Y3ROYW1lXSB8fCB7fTtcblxuXHRcdFx0T2JqZWN0LmtleXMoYmluZGluZ3NNYXBbcGFja2FnZU5hbWVdW3N0cnVjdE5hbWVdKS5mb3JFYWNoKChtZXRob2ROYW1lKSA9PiB7XG5cblx0XHRcdFx0d2luZG93LmdvW3BhY2thZ2VOYW1lXVtzdHJ1Y3ROYW1lXVttZXRob2ROYW1lXSA9IGZ1bmN0aW9uICgpIHtcblxuXHRcdFx0XHRcdC8vIE5vIHRpbWVvdXQgYnkgZGVmYXVsdFxuXHRcdFx0XHRcdGxldCB0aW1lb3V0ID0gMDtcblxuXHRcdFx0XHRcdC8vIEFjdHVhbCBmdW5jdGlvblxuXHRcdFx0XHRcdGZ1bmN0aW9uIGR5bmFtaWMoKSB7XG5cdFx0XHRcdFx0XHRjb25zdCBhcmdzID0gW10uc2xpY2UuY2FsbChhcmd1bWVudHMpO1xuXHRcdFx0XHRcdFx0cmV0dXJuIENhbGwoW3BhY2thZ2VOYW1lLCBzdHJ1Y3ROYW1lLCBtZXRob2ROYW1lXS5qb2luKCcuJyksIGFyZ3MsIHRpbWVvdXQpO1xuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdC8vIEFsbG93IHNldHRpbmcgdGltZW91dCB0byBmdW5jdGlvblxuXHRcdFx0XHRcdGR5bmFtaWMuc2V0VGltZW91dCA9IGZ1bmN0aW9uIChuZXdUaW1lb3V0KSB7XG5cdFx0XHRcdFx0XHR0aW1lb3V0ID0gbmV3VGltZW91dDtcblx0XHRcdFx0XHR9O1xuXG5cdFx0XHRcdFx0Ly8gQWxsb3cgZ2V0dGluZyB0aW1lb3V0IHRvIGZ1bmN0aW9uXG5cdFx0XHRcdFx0ZHluYW1pYy5nZXRUaW1lb3V0ID0gZnVuY3Rpb24gKCkge1xuXHRcdFx0XHRcdFx0cmV0dXJuIHRpbWVvdXQ7XG5cdFx0XHRcdFx0fTtcblxuXHRcdFx0XHRcdHJldHVybiBkeW5hbWljO1xuXHRcdFx0XHR9KCk7XG5cdFx0XHR9KTtcblx0XHR9KTtcblx0fSk7XG59XG4iLCAiLypcbiBfXHQgICBfX1x0ICBfIF9fXG58IHxcdCAvIC9fX18gXyhfKSAvX19fX1xufCB8IC98IC8gLyBfXyBgLyAvIC8gX19fL1xufCB8LyB8LyAvIC9fLyAvIC8gKF9fICApXG58X18vfF9fL1xcX18sXy9fL18vX19fXy9cblRoZSBlbGVjdHJvbiBhbHRlcm5hdGl2ZSBmb3IgR29cbihjKSBMZWEgQW50aG9ueSAyMDE5LXByZXNlbnRcbiovXG5cbi8qIGpzaGludCBlc3ZlcnNpb246IDkgKi9cblxuXG5pbXBvcnQge0NhbGx9IGZyb20gXCIuL2NhbGxzXCI7XG5cbmV4cG9ydCBmdW5jdGlvbiBXaW5kb3dSZWxvYWQoKSB7XG4gICAgd2luZG93LmxvY2F0aW9uLnJlbG9hZCgpO1xufVxuXG4vKipcbiAqIFBsYWNlIHRoZSB3aW5kb3cgaW4gdGhlIGNlbnRlciBvZiB0aGUgc2NyZWVuXG4gKlxuICogQGV4cG9ydFxuICovXG5leHBvcnQgZnVuY3Rpb24gV2luZG93Q2VudGVyKCkge1xuICAgIHdpbmRvdy5XYWlsc0ludm9rZSgnV2MnKTtcbn1cblxuLyoqXG4gKiBTZXRzIHRoZSB3aW5kb3cgdGl0bGVcbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gdGl0bGVcbiAqIEBleHBvcnRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFdpbmRvd1NldFRpdGxlKHRpdGxlKSB7XG4gICAgd2luZG93LldhaWxzSW52b2tlKCdXVCcgKyB0aXRsZSk7XG59XG5cbi8qKlxuICogTWFrZXMgdGhlIHdpbmRvdyBnbyBmdWxsc2NyZWVuXG4gKlxuICogQGV4cG9ydFxuICovXG5leHBvcnQgZnVuY3Rpb24gV2luZG93RnVsbHNjcmVlbigpIHtcbiAgICB3aW5kb3cuV2FpbHNJbnZva2UoJ1dGJyk7XG59XG5cbi8qKlxuICogUmV2ZXJ0cyB0aGUgd2luZG93IGZyb20gZnVsbHNjcmVlblxuICpcbiAqIEBleHBvcnRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFdpbmRvd1VuRnVsbHNjcmVlbigpIHtcbiAgICB3aW5kb3cuV2FpbHNJbnZva2UoJ1dmJyk7XG59XG5cbi8qKlxuICogU2V0IHRoZSBTaXplIG9mIHRoZSB3aW5kb3dcbiAqXG4gKiBAZXhwb3J0XG4gKiBAcGFyYW0ge251bWJlcn0gd2lkdGhcbiAqIEBwYXJhbSB7bnVtYmVyfSBoZWlnaHRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFdpbmRvd1NldFNpemUod2lkdGgsIGhlaWdodCkge1xuICAgIHdpbmRvdy5XYWlsc0ludm9rZSgnV3M6JyArIHdpZHRoICsgJzonICsgaGVpZ2h0KTtcbn1cblxuLyoqXG4gKiBHZXQgdGhlIFNpemUgb2YgdGhlIHdpbmRvd1xuICpcbiAqIEBleHBvcnRcbiAqIEByZXR1cm4ge1Byb21pc2U8e3c6IG51bWJlciwgaDogbnVtYmVyfT59IFRoZSBzaXplIG9mIHRoZSB3aW5kb3dcblxuICovXG5leHBvcnQgZnVuY3Rpb24gV2luZG93R2V0U2l6ZSgpIHtcbiAgICByZXR1cm4gQ2FsbChcIjp3YWlsczpXaW5kb3dHZXRTaXplXCIpO1xufVxuXG4vKipcbiAqIFNldCB0aGUgbWF4aW11bSBzaXplIG9mIHRoZSB3aW5kb3dcbiAqXG4gKiBAZXhwb3J0XG4gKiBAcGFyYW0ge251bWJlcn0gd2lkdGhcbiAqIEBwYXJhbSB7bnVtYmVyfSBoZWlnaHRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFdpbmRvd1NldE1heFNpemUod2lkdGgsIGhlaWdodCkge1xuICAgIHdpbmRvdy5XYWlsc0ludm9rZSgnV1o6JyArIHdpZHRoICsgJzonICsgaGVpZ2h0KTtcbn1cblxuLyoqXG4gKiBTZXQgdGhlIG1pbmltdW0gc2l6ZSBvZiB0aGUgd2luZG93XG4gKlxuICogQGV4cG9ydFxuICogQHBhcmFtIHtudW1iZXJ9IHdpZHRoXG4gKiBAcGFyYW0ge251bWJlcn0gaGVpZ2h0XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBXaW5kb3dTZXRNaW5TaXplKHdpZHRoLCBoZWlnaHQpIHtcbiAgICB3aW5kb3cuV2FpbHNJbnZva2UoJ1d6OicgKyB3aWR0aCArICc6JyArIGhlaWdodCk7XG59XG5cbi8qKlxuICogU2V0IHRoZSBQb3NpdGlvbiBvZiB0aGUgd2luZG93XG4gKlxuICogQGV4cG9ydFxuICogQHBhcmFtIHtudW1iZXJ9IHhcbiAqIEBwYXJhbSB7bnVtYmVyfSB5XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBXaW5kb3dTZXRQb3NpdGlvbih4LCB5KSB7XG4gICAgd2luZG93LldhaWxzSW52b2tlKCdXcDonICsgeCArICc6JyArIHkpO1xufVxuXG4vKipcbiAqIEdldCB0aGUgUG9zaXRpb24gb2YgdGhlIHdpbmRvd1xuICpcbiAqIEBleHBvcnRcbiAqIEByZXR1cm4ge1Byb21pc2U8e3g6IG51bWJlciwgeTogbnVtYmVyfT59IFRoZSBwb3NpdGlvbiBvZiB0aGUgd2luZG93XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBXaW5kb3dHZXRQb3NpdGlvbigpIHtcbiAgICByZXR1cm4gQ2FsbChcIjp3YWlsczpXaW5kb3dHZXRQb3NcIik7XG59XG5cbi8qKlxuICogSGlkZSB0aGUgV2luZG93XG4gKlxuICogQGV4cG9ydFxuICovXG5leHBvcnQgZnVuY3Rpb24gV2luZG93SGlkZSgpIHtcbiAgICB3aW5kb3cuV2FpbHNJbnZva2UoJ1dIJyk7XG59XG5cbi8qKlxuICogU2hvdyB0aGUgV2luZG93XG4gKlxuICogQGV4cG9ydFxuICovXG5leHBvcnQgZnVuY3Rpb24gV2luZG93U2hvdygpIHtcbiAgICB3aW5kb3cuV2FpbHNJbnZva2UoJ1dTJyk7XG59XG5cbi8qKlxuICogTWF4aW1pc2UgdGhlIFdpbmRvd1xuICpcbiAqIEBleHBvcnRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFdpbmRvd01heGltaXNlKCkge1xuICAgIHdpbmRvdy5XYWlsc0ludm9rZSgnV00nKTtcbn1cblxuLyoqXG4gKiBVbm1heGltaXNlIHRoZSBXaW5kb3dcbiAqXG4gKiBAZXhwb3J0XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBXaW5kb3dVbm1heGltaXNlKCkge1xuICAgIHdpbmRvdy5XYWlsc0ludm9rZSgnV1UnKTtcbn1cblxuLyoqXG4gKiBNaW5pbWlzZSB0aGUgV2luZG93XG4gKlxuICogQGV4cG9ydFxuICovXG5leHBvcnQgZnVuY3Rpb24gV2luZG93TWluaW1pc2UoKSB7XG4gICAgd2luZG93LldhaWxzSW52b2tlKCdXbScpO1xufVxuXG4vKipcbiAqIFVubWluaW1pc2UgdGhlIFdpbmRvd1xuICpcbiAqIEBleHBvcnRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFdpbmRvd1VubWluaW1pc2UoKSB7XG4gICAgd2luZG93LldhaWxzSW52b2tlKCdXdScpO1xufVxuXG5cbi8qKlxuICogU2V0cyB0aGUgYmFja2dyb3VuZCBjb2xvdXIgb2YgdGhlIHdpbmRvd1xuICpcbiAqIEBleHBvcnRcbiAqIEBwYXJhbSB7UkdCQX0gUkdCQSBiYWNrZ3JvdW5kIGNvbG91clxuICovXG5leHBvcnQgZnVuY3Rpb24gV2luZG93U2V0UkdCQShSR0JBKSB7XG4gICAgbGV0IHJnYmEgPSBKU09OLnN0cmluZ2lmeShSR0JBKTtcbiAgICB3aW5kb3cuV2FpbHNJbnZva2UoJ1dyOicgKyByZ2JhKTtcbn1cblxuIiwgIi8qKlxuICogQGRlc2NyaXB0aW9uOiBVc2UgdGhlIHN5c3RlbSBkZWZhdWx0IGJyb3dzZXIgdG8gb3BlbiB0aGUgdXJsXG4gKiBAcGFyYW0ge3N0cmluZ30gdXJsIFxuICogQHJldHVybiB7dm9pZH1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIEJyb3dzZXJPcGVuVVJMKHVybCkge1xuICB3aW5kb3cuV2FpbHNJbnZva2UoJ0JPOicgKyB1cmwpO1xufSIsICIvKlxuIF9cdCAgIF9fXHQgIF8gX19cbnwgfFx0IC8gL19fXyBfKF8pIC9fX19fXG58IHwgL3wgLyAvIF9fIGAvIC8gLyBfX18vXG58IHwvIHwvIC8gL18vIC8gLyAoX18gIClcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xuVGhlIGVsZWN0cm9uIGFsdGVybmF0aXZlIGZvciBHb1xuKGMpIExlYSBBbnRob255IDIwMTktcHJlc2VudFxuKi9cbi8qIGpzaGludCBlc3ZlcnNpb246IDkgKi9cbmltcG9ydCAqIGFzIExvZyBmcm9tICcuL2xvZyc7XG5pbXBvcnQge2V2ZW50TGlzdGVuZXJzLCBFdmVudHNFbWl0LCBFdmVudHNOb3RpZnksIEV2ZW50c09mZiwgRXZlbnRzT24sIEV2ZW50c09uY2UsIEV2ZW50c09uTXVsdGlwbGV9IGZyb20gJy4vZXZlbnRzJztcbmltcG9ydCB7Q2FsbGJhY2ssIGNhbGxiYWNrc30gZnJvbSAnLi9jYWxscyc7XG5pbXBvcnQge1NldEJpbmRpbmdzfSBmcm9tIFwiLi9iaW5kaW5nc1wiO1xuaW1wb3J0ICogYXMgV2luZG93IGZyb20gXCIuL3dpbmRvd1wiO1xuaW1wb3J0ICogYXMgQnJvd3NlciBmcm9tIFwiLi9icm93c2VyXCI7XG5cblxuZXhwb3J0IGZ1bmN0aW9uIFF1aXQoKSB7XG4gICAgd2luZG93LldhaWxzSW52b2tlKCdRJyk7XG59XG5cbi8vIFRoZSBKUyBydW50aW1lXG53aW5kb3cucnVudGltZSA9IHtcbiAgICAuLi5Mb2csXG4gICAgLi4uV2luZG93LFxuICAgIC4uLkJyb3dzZXIsXG4gICAgRXZlbnRzT24sXG4gICAgRXZlbnRzT25jZSxcbiAgICBFdmVudHNPbk11bHRpcGxlLFxuICAgIEV2ZW50c0VtaXQsXG4gICAgRXZlbnRzT2ZmLFxuICAgIFF1aXRcbn07XG5cbi8vIEludGVybmFsIHdhaWxzIGVuZHBvaW50c1xud2luZG93LndhaWxzID0ge1xuICAgIENhbGxiYWNrLFxuICAgIEV2ZW50c05vdGlmeSxcbiAgICBTZXRCaW5kaW5ncyxcbiAgICBldmVudExpc3RlbmVycyxcbiAgICBjYWxsYmFja3MsXG4gICAgZmxhZ3M6IHtcbiAgICAgICAgZGlzYWJsZVNjcm9sbGJhckRyYWc6IGZhbHNlLFxuICAgICAgICBkaXNhYmxlV2FpbHNEZWZhdWx0Q29udGV4dE1lbnU6IGZhbHNlLFxuICAgIH1cbn07XG5cbi8vIFNldCB0aGUgYmluZGluZ3NcbndpbmRvdy53YWlscy5TZXRCaW5kaW5ncyh3aW5kb3cud2FpbHNiaW5kaW5ncyk7XG5kZWxldGUgd2luZG93LndhaWxzLlNldEJpbmRpbmdzO1xuXG4vLyBUaGlzIGlzIGV2YWx1YXRlZCBhdCBidWlsZCB0aW1lIGluIHBhY2thZ2UuanNvblxuLy8gY29uc3QgZGV2ID0gMDtcbi8vIGNvbnN0IHByb2R1Y3Rpb24gPSAxO1xuaWYgKEVOViA9PT0gMCkge1xuICAgIGRlbGV0ZSB3aW5kb3cud2FpbHNiaW5kaW5ncztcbn1cblxuLy8gU2V0dXAgZHJhZyBoYW5kbGVyXG4vLyBCYXNlZCBvbiBjb2RlIGZyb206IGh0dHBzOi8vZ2l0aHViLmNvbS9wYXRyMG51cy9EZXNrR2FwXG53aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcignbW91c2Vkb3duJywgKGUpID0+IHtcbiAgICBsZXQgY3VycmVudEVsZW1lbnQgPSBlLnRhcmdldDtcbiAgICB3aGlsZSAoY3VycmVudEVsZW1lbnQgIT0gbnVsbCkge1xuICAgICAgICBpZiAoY3VycmVudEVsZW1lbnQuaGFzQXR0cmlidXRlKCdkYXRhLXdhaWxzLW5vLWRyYWcnKSkge1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH0gZWxzZSBpZiAoY3VycmVudEVsZW1lbnQuaGFzQXR0cmlidXRlKCdkYXRhLXdhaWxzLWRyYWcnKSkge1xuICAgICAgICAgICAgaWYgKHdpbmRvdy53YWlscy5mbGFncy5kaXNhYmxlU2Nyb2xsYmFyRHJhZykge1xuICAgICAgICAgICAgICAgIC8vIFRoaXMgY2hlY2tzIGZvciBjbGlja3Mgb24gdGhlIHNjcm9sbCBiYXJcbiAgICAgICAgICAgICAgICBpZiAoZS5vZmZzZXRYID4gZS50YXJnZXQuY2xpZW50V2lkdGggfHwgZS5vZmZzZXRZID4gZS50YXJnZXQuY2xpZW50SGVpZ2h0KSB7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHdpbmRvdy5XYWlsc0ludm9rZShcImRyYWdcIik7XG4gICAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgICBjdXJyZW50RWxlbWVudCA9IGN1cnJlbnRFbGVtZW50LnBhcmVudEVsZW1lbnQ7XG4gICAgfVxufSk7XG5cbi8vIFNldHVwIGNvbnRleHQgbWVudSBob29rXG53aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcignY29udGV4dG1lbnUnLCBmdW5jdGlvbiAoZSkge1xuICAgIGlmICh3aW5kb3cud2FpbHMuZmxhZ3MuZGlzYWJsZVdhaWxzRGVmYXVsdENvbnRleHRNZW51KSB7XG4gICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICB9XG59KTsiXSwKICAibWFwcGluZ3MiOiAiOzs7Ozs7Ozs7O0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBa0JBLDBCQUF3QixPQUFPLFNBQVM7QUFJdkMsV0FBTyxZQUFZLE1BQU0sUUFBUTtBQUFBO0FBUzNCLG9CQUFrQixTQUFTO0FBQ2pDLG1CQUFlLEtBQUs7QUFBQTtBQVNkLG9CQUFrQixTQUFTO0FBQ2pDLG1CQUFlLEtBQUs7QUFBQTtBQVNkLG9CQUFrQixTQUFTO0FBQ2pDLG1CQUFlLEtBQUs7QUFBQTtBQVNkLG1CQUFpQixTQUFTO0FBQ2hDLG1CQUFlLEtBQUs7QUFBQTtBQVNkLHNCQUFvQixTQUFTO0FBQ25DLG1CQUFlLEtBQUs7QUFBQTtBQVNkLG9CQUFrQixTQUFTO0FBQ2pDLG1CQUFlLEtBQUs7QUFBQTtBQVNkLG9CQUFrQixTQUFTO0FBQ2pDLG1CQUFlLEtBQUs7QUFBQTtBQVNkLHVCQUFxQixVQUFVO0FBQ3JDLG1CQUFlLEtBQUs7QUFBQTtBQUlkLE1BQU0sV0FBVztBQUFBLElBQ3ZCLE9BQU87QUFBQSxJQUNQLE9BQU87QUFBQSxJQUNQLE1BQU07QUFBQSxJQUNOLFNBQVM7QUFBQSxJQUNULE9BQU87QUFBQTs7O0FDN0ZSLHVCQUFlO0FBQUEsSUFPWCxZQUFZLFVBQVUsY0FBYztBQUVoQyxxQkFBZSxnQkFBZ0I7QUFHL0IsV0FBSyxXQUFXLENBQUMsU0FBUztBQUN0QixpQkFBUyxNQUFNLE1BQU07QUFFckIsWUFBSSxpQkFBaUIsSUFBSTtBQUNyQixpQkFBTztBQUFBO0FBR1gsd0JBQWdCO0FBQ2hCLGVBQU8saUJBQWlCO0FBQUE7QUFBQTtBQUFBO0FBSzdCLE1BQU0saUJBQWlCO0FBVXZCLDRCQUEwQixXQUFXLFVBQVUsY0FBYztBQUNoRSxtQkFBZSxhQUFhLGVBQWUsY0FBYztBQUN6RCxVQUFNLGVBQWUsSUFBSSxTQUFTLFVBQVU7QUFDNUMsbUJBQWUsV0FBVyxLQUFLO0FBQUE7QUFVNUIsb0JBQWtCLFdBQVcsVUFBVTtBQUMxQyxxQkFBaUIsV0FBVyxVQUFVO0FBQUE7QUFVbkMsc0JBQW9CLFdBQVcsVUFBVTtBQUM1QyxxQkFBaUIsV0FBVyxVQUFVO0FBQUE7QUFHMUMsMkJBQXlCLFdBQVc7QUFHaEMsUUFBSSxZQUFZLFVBQVU7QUFHMUIsUUFBSSxlQUFlLFlBQVk7QUFHM0IsWUFBTSx1QkFBdUIsZUFBZSxXQUFXO0FBR3ZELGVBQVMsUUFBUSxHQUFHLFFBQVEsZUFBZSxXQUFXLFFBQVEsU0FBUyxHQUFHO0FBR3RFLGNBQU0sV0FBVyxlQUFlLFdBQVc7QUFFM0MsWUFBSSxPQUFPLFVBQVU7QUFHckIsY0FBTSxVQUFVLFNBQVMsU0FBUztBQUNsQyxZQUFJLFNBQVM7QUFFVCwrQkFBcUIsT0FBTyxPQUFPO0FBQUE7QUFBQTtBQUszQyxxQkFBZSxhQUFhO0FBQUE7QUFBQTtBQVc3Qix3QkFBc0IsZUFBZTtBQUV4QyxRQUFJO0FBQ0osUUFBSTtBQUNBLGdCQUFVLEtBQUssTUFBTTtBQUFBLGFBQ2hCLEdBQVA7QUFDRSxZQUFNLFFBQVEsb0NBQW9DO0FBQ2xELFlBQU0sSUFBSSxNQUFNO0FBQUE7QUFFcEIsb0JBQWdCO0FBQUE7QUFTYixzQkFBb0IsV0FBVztBQUVsQyxVQUFNLFVBQVU7QUFBQSxNQUNaLE1BQU07QUFBQSxNQUNOLE1BQU0sR0FBRyxNQUFNLE1BQU0sV0FBVyxNQUFNO0FBQUE7QUFJMUMsb0JBQWdCO0FBR2hCLFdBQU8sWUFBWSxPQUFPLEtBQUssVUFBVTtBQUFBO0FBR3RDLHFCQUFtQixXQUFXO0FBRWpDLG1CQUFlLE9BQU87QUFHdEIsV0FBTyxZQUFZLE9BQU87QUFBQTs7O0FDbEp2QixNQUFNLFlBQVk7QUFPekIsMEJBQXdCO0FBQ3ZCLFFBQUksUUFBUSxJQUFJLFlBQVk7QUFDNUIsV0FBTyxPQUFPLE9BQU8sZ0JBQWdCLE9BQU87QUFBQTtBQVM3Qyx5QkFBdUI7QUFDdEIsV0FBTyxLQUFLLFdBQVc7QUFBQTtBQUl4QixNQUFJO0FBQ0osTUFBSSxPQUFPLFFBQVE7QUFDbEIsaUJBQWE7QUFBQSxTQUNQO0FBQ04saUJBQWE7QUFBQTtBQWtCUCxnQkFBYyxNQUFNLE1BQU0sU0FBUztBQUd6QyxRQUFJLFdBQVcsTUFBTTtBQUNwQixnQkFBVTtBQUFBO0FBSVgsV0FBTyxJQUFJLFFBQVEsU0FBVSxTQUFTLFFBQVE7QUFHN0MsVUFBSTtBQUNKLFNBQUc7QUFDRixxQkFBYSxPQUFPLE1BQU07QUFBQSxlQUNsQixVQUFVO0FBRW5CLFVBQUk7QUFFSixVQUFJLFVBQVUsR0FBRztBQUNoQix3QkFBZ0IsV0FBVyxXQUFZO0FBQ3RDLGlCQUFPLE1BQU0sYUFBYSxPQUFPLDZCQUE2QjtBQUFBLFdBQzVEO0FBQUE7QUFJSixnQkFBVSxjQUFjO0FBQUEsUUFDdkI7QUFBQSxRQUNBO0FBQUEsUUFDQTtBQUFBO0FBR0QsVUFBSTtBQUNILGNBQU0sVUFBVTtBQUFBLFVBQ2Y7QUFBQSxVQUNBO0FBQUEsVUFDQTtBQUFBO0FBSUQsZUFBTyxZQUFZLE1BQU0sS0FBSyxVQUFVO0FBQUEsZUFDaEMsR0FBUDtBQUVELGdCQUFRLE1BQU07QUFBQTtBQUFBO0FBQUE7QUFjVixvQkFBa0IsaUJBQWlCO0FBS3pDLFFBQUk7QUFDSixRQUFJO0FBQ0gsZ0JBQVUsS0FBSyxNQUFNO0FBQUEsYUFDYixHQUFQO0FBQ0QsWUFBTSxRQUFRLG9DQUFvQyxFQUFFLHFCQUFxQjtBQUN6RSxZQUFNLFNBQVM7QUFDZixZQUFNLElBQUksTUFBTTtBQUFBO0FBRWpCLFFBQUksYUFBYSxRQUFRO0FBQ3pCLFFBQUksZUFBZSxVQUFVO0FBQzdCLFFBQUksQ0FBQyxjQUFjO0FBQ2xCLFlBQU0sUUFBUSxhQUFhO0FBQzNCLGNBQVEsTUFBTTtBQUNkLFlBQU0sSUFBSSxNQUFNO0FBQUE7QUFFakIsaUJBQWEsYUFBYTtBQUUxQixXQUFPLFVBQVU7QUFFakIsUUFBSSxRQUFRLE9BQU87QUFDbEIsbUJBQWEsT0FBTyxRQUFRO0FBQUEsV0FDdEI7QUFDTixtQkFBYSxRQUFRLFFBQVE7QUFBQTtBQUFBOzs7QUM3SC9CLFNBQU8sS0FBSztBQUVMLHVCQUFxQixhQUFhO0FBQ3hDLFFBQUk7QUFDSCxvQkFBYyxLQUFLLE1BQU07QUFBQSxhQUNqQixHQUFQO0FBQ0QsY0FBUSxNQUFNO0FBQUE7QUFJZixXQUFPLEtBQUssT0FBTyxNQUFNO0FBR3pCLFdBQU8sS0FBSyxhQUFhLFFBQVEsQ0FBQyxnQkFBZ0I7QUFHakQsYUFBTyxHQUFHLGVBQWUsT0FBTyxHQUFHLGdCQUFnQjtBQUduRCxhQUFPLEtBQUssWUFBWSxjQUFjLFFBQVEsQ0FBQyxlQUFlO0FBRzdELGVBQU8sR0FBRyxhQUFhLGNBQWMsT0FBTyxHQUFHLGFBQWEsZUFBZTtBQUUzRSxlQUFPLEtBQUssWUFBWSxhQUFhLGFBQWEsUUFBUSxDQUFDLGVBQWU7QUFFekUsaUJBQU8sR0FBRyxhQUFhLFlBQVksY0FBYyxXQUFZO0FBRzVELGdCQUFJLFVBQVU7QUFHZCwrQkFBbUI7QUFDbEIsb0JBQU0sT0FBTyxHQUFHLE1BQU0sS0FBSztBQUMzQixxQkFBTyxLQUFLLENBQUMsYUFBYSxZQUFZLFlBQVksS0FBSyxNQUFNLE1BQU07QUFBQTtBQUlwRSxvQkFBUSxhQUFhLFNBQVUsWUFBWTtBQUMxQyx3QkFBVTtBQUFBO0FBSVgsb0JBQVEsYUFBYSxXQUFZO0FBQ2hDLHFCQUFPO0FBQUE7QUFHUixtQkFBTztBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7OztBQzdEWjtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFlTywwQkFBd0I7QUFDM0IsV0FBTyxTQUFTO0FBQUE7QUFRYiwwQkFBd0I7QUFDM0IsV0FBTyxZQUFZO0FBQUE7QUFTaEIsMEJBQXdCLE9BQU87QUFDbEMsV0FBTyxZQUFZLE9BQU87QUFBQTtBQVF2Qiw4QkFBNEI7QUFDL0IsV0FBTyxZQUFZO0FBQUE7QUFRaEIsZ0NBQThCO0FBQ2pDLFdBQU8sWUFBWTtBQUFBO0FBVWhCLHlCQUF1QixPQUFPLFFBQVE7QUFDekMsV0FBTyxZQUFZLFFBQVEsUUFBUSxNQUFNO0FBQUE7QUFVdEMsMkJBQXlCO0FBQzVCLFdBQU8sS0FBSztBQUFBO0FBVVQsNEJBQTBCLE9BQU8sUUFBUTtBQUM1QyxXQUFPLFlBQVksUUFBUSxRQUFRLE1BQU07QUFBQTtBQVV0Qyw0QkFBMEIsT0FBTyxRQUFRO0FBQzVDLFdBQU8sWUFBWSxRQUFRLFFBQVEsTUFBTTtBQUFBO0FBVXRDLDZCQUEyQixHQUFHLEdBQUc7QUFDcEMsV0FBTyxZQUFZLFFBQVEsSUFBSSxNQUFNO0FBQUE7QUFTbEMsK0JBQTZCO0FBQ2hDLFdBQU8sS0FBSztBQUFBO0FBUVQsd0JBQXNCO0FBQ3pCLFdBQU8sWUFBWTtBQUFBO0FBUWhCLHdCQUFzQjtBQUN6QixXQUFPLFlBQVk7QUFBQTtBQVFoQiw0QkFBMEI7QUFDN0IsV0FBTyxZQUFZO0FBQUE7QUFRaEIsOEJBQTRCO0FBQy9CLFdBQU8sWUFBWTtBQUFBO0FBUWhCLDRCQUEwQjtBQUM3QixXQUFPLFlBQVk7QUFBQTtBQVFoQiw4QkFBNEI7QUFDL0IsV0FBTyxZQUFZO0FBQUE7QUFVaEIseUJBQXVCLE1BQU07QUFDaEMsUUFBSSxPQUFPLEtBQUssVUFBVTtBQUMxQixXQUFPLFlBQVksUUFBUTtBQUFBOzs7QUN4TC9CO0FBQUE7QUFBQTtBQUFBO0FBS08sMEJBQXdCLEtBQUs7QUFDbEMsV0FBTyxZQUFZLFFBQVE7QUFBQTs7O0FDWXRCLGtCQUFnQjtBQUNuQixXQUFPLFlBQVk7QUFBQTtBQUl2QixTQUFPLFVBQVU7QUFBQSxPQUNWO0FBQUEsT0FDQTtBQUFBLE9BQ0E7QUFBQSxJQUNIO0FBQUEsSUFDQTtBQUFBLElBQ0E7QUFBQSxJQUNBO0FBQUEsSUFDQTtBQUFBLElBQ0E7QUFBQTtBQUlKLFNBQU8sUUFBUTtBQUFBLElBQ1g7QUFBQSxJQUNBO0FBQUEsSUFDQTtBQUFBLElBQ0E7QUFBQSxJQUNBO0FBQUEsSUFDQSxPQUFPO0FBQUEsTUFDSCxzQkFBc0I7QUFBQSxNQUN0QixnQ0FBZ0M7QUFBQTtBQUFBO0FBS3hDLFNBQU8sTUFBTSxZQUFZLE9BQU87QUFDaEMsU0FBTyxPQUFPLE1BQU07QUFLcEIsTUFBSSxNQUFXO0FBQ1gsV0FBTyxPQUFPO0FBQUE7QUFLbEIsU0FBTyxpQkFBaUIsYUFBYSxDQUFDLE1BQU07QUFDeEMsUUFBSSxpQkFBaUIsRUFBRTtBQUN2QixXQUFPLGtCQUFrQixNQUFNO0FBQzNCLFVBQUksZUFBZSxhQUFhLHVCQUF1QjtBQUNuRDtBQUFBLGlCQUNPLGVBQWUsYUFBYSxvQkFBb0I7QUFDdkQsWUFBSSxPQUFPLE1BQU0sTUFBTSxzQkFBc0I7QUFFekMsY0FBSSxFQUFFLFVBQVUsRUFBRSxPQUFPLGVBQWUsRUFBRSxVQUFVLEVBQUUsT0FBTyxjQUFjO0FBQ3ZFO0FBQUE7QUFBQTtBQUdSLGVBQU8sWUFBWTtBQUNuQixVQUFFO0FBQ0Y7QUFBQTtBQUVKLHVCQUFpQixlQUFlO0FBQUE7QUFBQTtBQUt4QyxTQUFPLGlCQUFpQixlQUFlLFNBQVUsR0FBRztBQUNoRCxRQUFJLE9BQU8sTUFBTSxNQUFNLGdDQUFnQztBQUNuRCxRQUFFO0FBQUE7QUFBQTsiLAogICJuYW1lcyI6IFtdCn0K
diff --git a/v2/internal/frontend/runtime/runtime_prod_desktop.go b/v2/internal/frontend/runtime/runtime_prod_desktop.go
new file mode 100644
index 000000000..feba8a847
--- /dev/null
+++ b/v2/internal/frontend/runtime/runtime_prod_desktop.go
@@ -0,0 +1,8 @@
+//go:build production && desktop
+
+package runtime
+
+import _ "embed"
+
+//go:embed runtime_prod_desktop.js
+var RuntimeDesktopJS []byte
diff --git a/v2/internal/frontend/runtime/runtime_prod_desktop.js b/v2/internal/frontend/runtime/runtime_prod_desktop.js
new file mode 100644
index 000000000..75a7b6924
--- /dev/null
+++ b/v2/internal/frontend/runtime/runtime_prod_desktop.js
@@ -0,0 +1 @@
+(()=>{var x=Object.defineProperty;var h=n=>x(n,"__esModule",{value:!0});var u=(n,o)=>{h(n);for(var e in o)x(n,e,{get:o[e],enumerable:!0})};var W={};u(W,{LogDebug:()=>C,LogError:()=>J,LogFatal:()=>F,LogInfo:()=>B,LogLevel:()=>U,LogPrint:()=>R,LogTrace:()=>D,LogWarning:()=>T,SetLogLevel:()=>G});function l(n,o){window.WailsInvoke("L"+n+o)}function D(n){l("T",n)}function R(n){l("P",n)}function C(n){l("D",n)}function B(n){l("I",n)}function T(n){l("W",n)}function J(n){l("E",n)}function F(n){l("F",n)}function G(n){l("S",n)}var U={TRACE:1,DEBUG:2,INFO:3,WARNING:4,ERROR:5};var E=class{constructor(o,e){e=e||-1,this.Callback=t=>(o.apply(null,t),e===-1?!1:(e-=1,e===0))}},s={};function d(n,o,e){s[n]=s[n]||[];let t=new E(o,e);s[n].push(t)}function I(n,o){d(n,o,-1)}function k(n,o){d(n,o,1)}function S(n){let o=n.name;if(s[o]){let e=s[o].slice();for(let t=0;t0&&(w=setTimeout(function(){r(Error("Call to "+n+" timed out. Request ID: "+i))},e)),a[i]={timeoutHandle:w,reject:r,resolve:t};try{let f={name:n,args:o,callbackID:i};window.WailsInvoke("C"+JSON.stringify(f))}catch(f){console.error(f)}})}function L(n){var o;try{o=JSON.parse(n)}catch(r){let i=`Invalid JSON passed to callback: ${r.message}. Message: ${n}`;throw wails.LogDebug(i),new Error(i)}var e=o.callbackid,t=a[e];if(!t){let r=`Callback '${e}' not registered!!!`;throw console.error(r),new Error(r)}clearTimeout(t.timeoutHandle),delete a[e],o.error?t.reject(o.error):t.resolve(o.result)}window.go={};function O(n){try{n=JSON.parse(n)}catch(o){console.error(o)}window.go=window.go||{},Object.keys(n).forEach(o=>{window.go[o]=window.go[o]||{},Object.keys(n[o]).forEach(e=>{window.go[o][e]=window.go[o][e]||{},Object.keys(n[o][e]).forEach(t=>{window.go[o][e][t]=function(){let r=0;function i(){let w=[].slice.call(arguments);return c([o,e,t].join("."),w,r)}return i.setTimeout=function(w){r=w},i.getTimeout=function(){return r},i}()})})})}var v={};u(v,{WindowCenter:()=>M,WindowFullscreen:()=>j,WindowGetPosition:()=>Y,WindowGetSize:()=>V,WindowHide:()=>Z,WindowMaximise:()=>_,WindowMinimise:()=>on,WindowReload:()=>H,WindowSetMaxSize:()=>X,WindowSetMinSize:()=>q,WindowSetPosition:()=>N,WindowSetRGBA:()=>tn,WindowSetSize:()=>Q,WindowSetTitle:()=>P,WindowShow:()=>K,WindowUnFullscreen:()=>$,WindowUnmaximise:()=>nn,WindowUnminimise:()=>en});function H(){window.location.reload()}function M(){window.WailsInvoke("Wc")}function P(n){window.WailsInvoke("WT"+n)}function j(){window.WailsInvoke("WF")}function $(){window.WailsInvoke("Wf")}function Q(n,o){window.WailsInvoke("Ws:"+n+":"+o)}function V(){return c(":wails:WindowGetSize")}function X(n,o){window.WailsInvoke("WZ:"+n+":"+o)}function q(n,o){window.WailsInvoke("Wz:"+n+":"+o)}function N(n,o){window.WailsInvoke("Wp:"+n+":"+o)}function Y(){return c(":wails:WindowGetPos")}function Z(){window.WailsInvoke("WH")}function K(){window.WailsInvoke("WS")}function _(){window.WailsInvoke("WM")}function nn(){window.WailsInvoke("WU")}function on(){window.WailsInvoke("Wm")}function en(){window.WailsInvoke("Wu")}function tn(n){let o=JSON.stringify(n);window.WailsInvoke("Wr:"+o)}var g={};u(g,{BrowserOpenURL:()=>rn});function rn(n){window.WailsInvoke("BO:"+n)}function sn(){window.WailsInvoke("Q")}window.runtime={...W,...v,...g,EventsOn:I,EventsOnce:k,EventsOnMultiple:d,EventsEmit:b,EventsOff:y,Quit:sn};window.wails={Callback:L,EventsNotify:m,SetBindings:O,eventListeners:s,callbacks:a,flags:{disableScrollbarDrag:!1,disableWailsDefaultContextMenu:!1}};window.wails.SetBindings(window.wailsbindings);delete window.wails.SetBindings;window.addEventListener("mousedown",n=>{let o=n.target;for(;o!=null&&!o.hasAttribute("data-wails-no-drag");){if(o.hasAttribute("data-wails-drag")){if(window.wails.flags.disableScrollbarDrag&&(n.offsetX>n.target.clientWidth||n.offsetY>n.target.clientHeight))break;window.WailsInvoke("drag"),n.preventDefault();break}o=o.parentElement}});window.addEventListener("contextmenu",function(n){window.wails.flags.disableWailsDefaultContextMenu&&n.preventDefault()});})();
diff --git a/v2/internal/frontend/runtime/wrapper/README.md b/v2/internal/frontend/runtime/wrapper/README.md
new file mode 100644
index 000000000..a743cffbb
--- /dev/null
+++ b/v2/internal/frontend/runtime/wrapper/README.md
@@ -0,0 +1,4 @@
+# Wails Runtime
+
+This module is the Javascript runtime library for the [Wails](https://wails.app) framework. It is intended to be
+installed as part of a [Wails](https://wails.app) project, not a standalone module.
diff --git a/v2/internal/frontend/runtime/wrapper/browser.js b/v2/internal/frontend/runtime/wrapper/browser.js
new file mode 100644
index 000000000..f1854820b
--- /dev/null
+++ b/v2/internal/frontend/runtime/wrapper/browser.js
@@ -0,0 +1,8 @@
+/**
+ * @description: Use the system default browser to open the url
+ * @param {string} url
+ * @return {void}
+ */
+export function BrowserOpenURL(url) {
+ window.runtime.BrowserOpenURL(url);
+}
\ No newline at end of file
diff --git a/v2/internal/frontend/runtime/wrapper/events.js b/v2/internal/frontend/runtime/wrapper/events.js
new file mode 100644
index 000000000..623dad51a
--- /dev/null
+++ b/v2/internal/frontend/runtime/wrapper/events.js
@@ -0,0 +1,58 @@
+/*
+ _ __ _ __
+| | / /___ _(_) /____
+| | /| / / __ `/ / / ___/
+| |/ |/ / /_/ / / (__ )
+|__/|__/\__,_/_/_/____/
+The electron alternative for Go
+(c) Lea Anthony 2019-present
+*/
+
+/* jshint esversion: 9 */
+
+
+/**
+ * Registers an event listener that will be invoked `maxCallbacks` times before being destroyed
+ *
+ * @export
+ * @param {string} eventName
+ * @param {function} callback
+ * @param {number} maxCallbacks
+ */
+export function EventsOnMultiple(eventName, callback, maxCallbacks) {
+ window.runtime.EventsOnMultiple(eventName, callback, maxCallbacks);
+}
+
+/**
+ * Registers an event listener that will be invoked every time the event is emitted
+ *
+ * @export
+ * @param {string} eventName
+ * @param {function} callback
+ */
+export function EventsOn(eventName, callback) {
+ OnMultiple(eventName, callback, -1);
+}
+
+/**
+ * Registers an event listener that will be invoked once then destroyed
+ *
+ * @export
+ * @param {string} eventName
+ * @param {function} callback
+ */
+export function EventsOnce(eventName, callback) {
+ OnMultiple(eventName, callback, 1);
+}
+
+
+/**
+ * Emit an event with the given name and data
+ *
+ * @export
+ * @param {string} eventName
+ */
+export function EventsEmit(eventName) {
+ let args = [eventName].slice.call(arguments);
+ return window.runtime.EventsEmit.apply(null, args);
+}
diff --git a/v2/internal/frontend/runtime/wrapper/log.js b/v2/internal/frontend/runtime/wrapper/log.js
new file mode 100644
index 000000000..977abf5f4
--- /dev/null
+++ b/v2/internal/frontend/runtime/wrapper/log.js
@@ -0,0 +1,72 @@
+/*
+ _ __ _ __
+| | / /___ _(_) /____
+| | /| / / __ `/ / / ___/
+| |/ |/ / /_/ / / (__ )
+|__/|__/\__,_/_/_/____/
+The electron alternative for Go
+(c) Lea Anthony 2019-present
+*/
+
+/* jshint esversion: 6 */
+
+
+/**
+ * Log the given trace message with the backend
+ *
+ * @export
+ * @param {string} message
+ */
+export function LogTrace(message) {
+ window.runtime.LogTrace(message);
+}
+
+/**
+ * Log the given debug message with the backend
+ *
+ * @export
+ * @param {string} message
+ */
+export function LogDebug(message) {
+ window.runtime.LogDebug(message);
+}
+
+/**
+ * Log the given info message with the backend
+ *
+ * @export
+ * @param {string} message
+ */
+export function LogInfo(message) {
+ window.runtime.LogInfo(message);
+}
+
+/**
+ * Log the given warning message with the backend
+ *
+ * @export
+ * @param {string} message
+ */
+export function LogWarning(message) {
+ window.runtime.LogWarning(message);
+}
+
+/**
+ * Log the given error message with the backend
+ *
+ * @export
+ * @param {string} message
+ */
+export function LogError(message) {
+ window.runtime.LogError(message);
+}
+
+/**
+ * Log the given fatal message with the backend
+ *
+ * @export
+ * @param {string} message
+ */
+export function LogFatal(message) {
+ window.runtime.LogFatal(message);
+}
diff --git a/v2/internal/frontend/runtime/wrapper/main.js b/v2/internal/frontend/runtime/wrapper/main.js
new file mode 100644
index 000000000..8be95ac4f
--- /dev/null
+++ b/v2/internal/frontend/runtime/wrapper/main.js
@@ -0,0 +1,28 @@
+/*
+ _ __ _ __
+| | / /___ _(_) /____
+| | /| / / __ `/ / / ___/
+| |/ |/ / /_/ / / (__ )
+|__/|__/\__,_/_/_/____/
+The electron alternative for Go
+(c) Lea Anthony 2019-present
+*/
+/* jshint esversion: 9 */
+
+import * as Log from "./log";
+import * as Events from './events';
+import * as Window from './window';
+import * as Browser from './browser';
+
+export function Quit() {
+ window.runtime.Quit();
+}
+
+
+export default {
+ ...Log,
+ ...Events,
+ ...Window,
+ ...Browser,
+ Quit
+};
\ No newline at end of file
diff --git a/v2/internal/frontend/runtime/wrapper/package-lock.json b/v2/internal/frontend/runtime/wrapper/package-lock.json
new file mode 100644
index 000000000..058e19cf3
--- /dev/null
+++ b/v2/internal/frontend/runtime/wrapper/package-lock.json
@@ -0,0 +1,13 @@
+{
+ "name": "@wailsapp/runtime",
+ "version": "2.0.0",
+ "lockfileVersion": 2,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "@wailsapp/runtime",
+ "version": "2.0.0",
+ "license": "MIT"
+ }
+ }
+}
diff --git a/v2/internal/frontend/runtime/wrapper/package.json b/v2/internal/frontend/runtime/wrapper/package.json
new file mode 100644
index 000000000..1e7c8a5d7
--- /dev/null
+++ b/v2/internal/frontend/runtime/wrapper/package.json
@@ -0,0 +1,24 @@
+{
+ "name": "@wailsapp/runtime",
+ "version": "2.0.0",
+ "description": "Wails Javascript runtime library",
+ "main": "runtime.js",
+ "types": "runtime.d.ts",
+ "scripts": {
+ },
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/wailsapp/wails.git"
+ },
+ "keywords": [
+ "Wails",
+ "Javascript",
+ "Go"
+ ],
+ "author": "Lea Anthony ",
+ "license": "MIT",
+ "bugs": {
+ "url": "https://github.com/wailsapp/wails/issues"
+ },
+ "homepage": "https://github.com/wailsapp/wails#readme"
+}
diff --git a/v2/internal/frontend/runtime/wrapper/runtime.d.ts b/v2/internal/frontend/runtime/wrapper/runtime.d.ts
new file mode 100644
index 000000000..233a67a96
--- /dev/null
+++ b/v2/internal/frontend/runtime/wrapper/runtime.d.ts
@@ -0,0 +1,87 @@
+interface Position {
+ x: number;
+ y: number;
+}
+
+interface Size {
+ w: number;
+ h: number;
+}
+
+interface RGBA {
+ r: number;
+ g: number;
+ b: number;
+ a: number;
+}
+
+
+interface runtime {
+ EventsEmit(eventName: string, data?: any): void;
+
+ EventsOn(eventName: string, callback: (data?: any) => void): void;
+
+ EventsOnMultiple(eventName: string, callback: (data?: any) => void, maxCallbacks: number): void;
+
+ EventsOnce(eventName: string, callback: (data?: any) => void): void;
+
+ LogTrace(message: string): void;
+
+ LogDebug(message: string): void;
+
+ LogError(message: string): void;
+
+ LogFatal(message: string): void;
+
+ LogInfo(message: string): void;
+
+ LogWarning(message: string): void;
+
+ WindowReload(): void;
+
+ WindowCenter(): void;
+
+ WindowSetTitle(title: string): void;
+
+ WindowFullscreen(): void;
+
+ WindowUnFullscreen(): void;
+
+ WindowSetSize(width: number, height: number): Promise;
+
+ WindowGetSize(): Promise;
+
+ WindowSetMaxSize(width: number, height: number): void;
+
+ WindowSetMinSize(width: number, height: number): void;
+
+ WindowSetPosition(x: number, y: number): void;
+
+ WindowGetPosition(): Promise;
+
+ WindowHide(): void;
+
+ WindowShow(): void;
+
+ WindowMaximise(): void;
+
+ WindowUnmaximise(): void;
+
+ WindowMinimise(): void;
+
+ WindowUnminimise(): void;
+
+ WindowSetRGBA(rgba: RGBA): void;
+
+ BrowserOpenURL(url: string): void;
+
+ Quit(): void;
+}
+
+declare global {
+ interface Window {
+ runtime: runtime;
+ }
+}
+
+export { };
diff --git a/v2/internal/frontend/runtime/wrapper/runtime.js b/v2/internal/frontend/runtime/wrapper/runtime.js
new file mode 100644
index 000000000..8a2b098a7
--- /dev/null
+++ b/v2/internal/frontend/runtime/wrapper/runtime.js
@@ -0,0 +1 @@
+(()=>{var d=Object.defineProperty;var m=n=>d(n,"__esModule",{value:!0});var t=(n,i)=>{m(n);for(var o in i)d(n,o,{get:i[o],enumerable:!0})};var e={};t(e,{LogDebug:()=>c,LogError:()=>x,LogFatal:()=>s,LogInfo:()=>W,LogTrace:()=>p,LogWarning:()=>f});function p(n){window.runtime.LogTrace(n)}function c(n){window.runtime.LogDebug(n)}function W(n){window.runtime.LogInfo(n)}function f(n){window.runtime.LogWarning(n)}function x(n){window.runtime.LogError(n)}function s(n){window.runtime.LogFatal(n)}var w={};t(w,{EventsEmit:()=>g,EventsOn:()=>a,EventsOnMultiple:()=>l,EventsOnce:()=>S});function l(n,i,o){window.runtime.EventsOnMultiple(n,i,o)}function a(n,i){OnMultiple(n,i,-1)}function S(n,i){OnMultiple(n,i,1)}function g(n){let i=[n].slice.call(arguments);return window.runtime.EventsEmit.apply(null,i)}var r={};t(r,{WindowCenter:()=>M,WindowFullscreen:()=>v,WindowGetPosition:()=>B,WindowGetSize:()=>O,WindowHide:()=>P,WindowMaximise:()=>b,WindowMinimise:()=>A,WindowReload:()=>L,WindowSetMaxSize:()=>F,WindowSetMinSize:()=>G,WindowSetPosition:()=>R,WindowSetRGBA:()=>D,WindowSetSize:()=>U,WindowSetTitle:()=>E,WindowShow:()=>T,WindowUnFullscreen:()=>z,WindowUnmaximise:()=>h,WindowUnminimise:()=>C});function L(){window.runtime.WindowReload()}function M(){window.runtime.WindowCenter()}function E(n){window.runtime.WindowSetTitle(n)}function v(){window.runtime.WindowFullscreen()}function z(){window.runtime.WindowUnFullscreen()}function O(){window.runtime.WindowGetSize()}function U(n,i){window.runtime.WindowSetSize(n,i)}function F(n,i){window.runtime.WindowSetMaxSize(n,i)}function G(n,i){window.runtime.WindowSetMinSize(n,i)}function R(n,i){window.runtime.WindowSetPosition(n,i)}function B(){window.runtime.WindowGetPosition()}function P(){window.runtime.WindowHide()}function T(){window.runtime.WindowShow()}function b(){window.runtime.WindowMaximise()}function h(){window.runtime.WindowUnmaximise()}function A(){window.runtime.WindowMinimise()}function C(){window.runtime.WindowUnminimise()}function D(n){window.runtime.WindowSetRGBA(n)}var u={};t(u,{BrowserOpenURL:()=>H});function H(n){window.runtime.BrowserOpenURL(n)}function I(){window.runtime.Quit()}var y={...e,...w,...r,...u,Quit:I};})();
diff --git a/v2/internal/frontend/runtime/wrapper/window.js b/v2/internal/frontend/runtime/wrapper/window.js
new file mode 100644
index 000000000..2ef54e3ac
--- /dev/null
+++ b/v2/internal/frontend/runtime/wrapper/window.js
@@ -0,0 +1,187 @@
+/*
+ _ __ _ __
+| | / /___ _(_) /____
+| | /| / / __ `/ / / ___/
+| |/ |/ / /_/ / / (__ )
+|__/|__/\__,_/_/_/____/
+The electron alternative for Go
+(c) Lea Anthony 2019-present
+*/
+
+/* jshint esversion: 9 */
+
+/**
+ * Reloads the Window
+ *
+ * @export
+ */
+export function WindowReload() {
+ window.runtime.WindowReload();
+}
+
+/**
+ * Place the window in the center of the screen
+ *
+ * @export
+ */
+export function WindowCenter() {
+ window.runtime.WindowCenter();
+}
+
+/**
+ * Sets the window title
+ *
+ * @param {string} title
+ * @export
+ */
+export function WindowSetTitle(title) {
+ window.runtime.WindowSetTitle(title);
+}
+
+/**
+ * Makes the window go fullscreen
+ *
+ * @export
+ */
+export function WindowFullscreen() {
+ window.runtime.WindowFullscreen();
+}
+
+/**
+ * Reverts the window from fullscreen
+ *
+ * @export
+ */
+export function WindowUnFullscreen() {
+ window.runtime.WindowUnFullscreen();
+}
+
+/**
+ * Get the Size of the window
+ *
+ * @export
+ * @return {Promise<{w: number, h: number}>} The size of the window
+
+ */
+export function WindowGetSize() {
+ window.runtime.WindowGetSize();
+}
+
+
+/**
+ * Set the Size of the window
+ *
+ * @export
+ * @param {number} width
+ * @param {number} height
+ */
+export function WindowSetSize(width, height) {
+ window.runtime.WindowSetSize(width, height);
+}
+
+/**
+ * Set the maximum size of the window
+ *
+ * @export
+ * @param {number} width
+ * @param {number} height
+ */
+export function WindowSetMaxSize(width, height) {
+ window.runtime.WindowSetMaxSize(width, height);
+}
+
+/**
+ * Set the minimum size of the window
+ *
+ * @export
+ * @param {number} width
+ * @param {number} height
+ */
+export function WindowSetMinSize(width, height) {
+ window.runtime.WindowSetMinSize(width, height);
+}
+
+/**
+ * Set the Position of the window
+ *
+ * @export
+ * @param {number} x
+ * @param {number} y
+ */
+export function WindowSetPosition(x, y) {
+ window.runtime.WindowSetPosition(x, y);
+}
+
+/**
+ * Get the Position of the window
+ *
+ * @export
+ * @return {Promise<{x: number, y: number}>} The position of the window
+ */
+export function WindowGetPosition() {
+ window.runtime.WindowGetPosition();
+}
+
+/**
+ * Hide the Window
+ *
+ * @export
+ */
+export function WindowHide() {
+ window.runtime.WindowHide();
+}
+
+/**
+ * Show the Window
+ *
+ * @export
+ */
+export function WindowShow() {
+ window.runtime.WindowShow();
+}
+
+/**
+ * Maximise the Window
+ *
+ * @export
+ */
+export function WindowMaximise() {
+ window.runtime.WindowMaximise();
+}
+
+/**
+ * Unmaximise the Window
+ *
+ * @export
+ */
+export function WindowUnmaximise() {
+ window.runtime.WindowUnmaximise();
+}
+
+/**
+ * Minimise the Window
+ *
+ * @export
+ */
+export function WindowMinimise() {
+ window.runtime.WindowMinimise();
+}
+
+/**
+ * Unminimise the Window
+ *
+ * @export
+ */
+export function WindowUnminimise() {
+ window.runtime.WindowUnminimise();
+}
+
+/**
+ * Sets the background colour of the window
+ *
+ * @export
+ * @param {RGBA} RGBA background colour
+ */
+export function WindowSetRGBA(RGBA) {
+ window.runtime.WindowSetRGBA(RGBA);
+}
diff --git a/v2/internal/frontend/runtime/wrapper/wrapper.go b/v2/internal/frontend/runtime/wrapper/wrapper.go
new file mode 100644
index 000000000..94853bc7c
--- /dev/null
+++ b/v2/internal/frontend/runtime/wrapper/wrapper.go
@@ -0,0 +1,6 @@
+package wrapper
+
+import "embed"
+
+//go:embed runtime.js runtime.d.ts package.json
+var RuntimeWrapper embed.FS
diff --git a/v2/internal/fs/fs.go b/v2/internal/fs/fs.go
new file mode 100644
index 000000000..9bb192209
--- /dev/null
+++ b/v2/internal/fs/fs.go
@@ -0,0 +1,397 @@
+package fs
+
+import (
+ "crypto/md5"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "os"
+ "path/filepath"
+ "runtime"
+ "unsafe"
+
+ "github.com/leaanthony/slicer"
+)
+
+// LocalDirectory gets the caller's file directory
+// Equivalent to node's __DIRNAME
+func LocalDirectory() string {
+ _, thisFile, _, _ := runtime.Caller(1)
+ return filepath.Dir(thisFile)
+}
+
+// RelativeToCwd returns an absolute path based on the cwd
+// and the given relative path
+func RelativeToCwd(relativePath string) (string, error) {
+ cwd, err := os.Getwd()
+ if err != nil {
+ return "", err
+ }
+
+ return filepath.Join(cwd, relativePath), nil
+}
+
+// Mkdir will create the given directory
+func Mkdir(dirname string) error {
+ return os.Mkdir(dirname, 0755)
+}
+
+// MkDirs creates the given nested directories.
+// Returns error on failure
+func MkDirs(fullPath string, mode ...os.FileMode) error {
+ var perms os.FileMode
+ perms = 0755
+ if len(mode) == 1 {
+ perms = mode[0]
+ }
+ return os.MkdirAll(fullPath, perms)
+}
+
+// MoveFile attempts to move the source file to the target
+// Target is a fully qualified path to a file *name*, not a
+// directory
+func MoveFile(source string, target string) error {
+ return os.Rename(source, target)
+}
+
+// DeleteFile will delete the given file
+func DeleteFile(filename string) error {
+ return os.Remove(filename)
+}
+
+// CopyFile from source to target
+func CopyFile(source string, target string) error {
+ s, err := os.Open(source)
+ if err != nil {
+ return err
+ }
+ defer s.Close()
+ d, err := os.Create(target)
+ if err != nil {
+ return err
+ }
+ if _, err := io.Copy(d, s); err != nil {
+ d.Close()
+ return err
+ }
+ return d.Close()
+}
+
+// DirExists - Returns true if the given path resolves to a directory on the filesystem
+func DirExists(path string) bool {
+ fi, err := os.Lstat(path)
+ if err != nil {
+ return false
+ }
+
+ return fi.Mode().IsDir()
+}
+
+// FileExists returns a boolean value indicating whether
+// the given file exists
+func FileExists(path string) bool {
+ fi, err := os.Lstat(path)
+ if err != nil {
+ return false
+ }
+
+ return fi.Mode().IsRegular()
+}
+
+// RelativePath returns a qualified path created by joining the
+// directory of the calling file and the given relative path.
+//
+// Example: RelativePath("..") in *this* file would give you '/path/to/wails2/v2/internal`
+func RelativePath(relativepath string, optionalpaths ...string) string {
+ _, thisFile, _, _ := runtime.Caller(1)
+ localDir := filepath.Dir(thisFile)
+
+ // If we have optional paths, join them to the relativepath
+ if len(optionalpaths) > 0 {
+ paths := []string{relativepath}
+ paths = append(paths, optionalpaths...)
+ relativepath = filepath.Join(paths...)
+ }
+ result, err := filepath.Abs(filepath.Join(localDir, relativepath))
+ if err != nil {
+ // I'm allowing this for 1 reason only: It's fatal if the path
+ // supplied is wrong as it's only used internally in Wails. If we get
+ // that path wrong, we should know about it immediately. The other reason is
+ // that it cuts down a ton of unnecassary error handling.
+ panic(err)
+ }
+ return result
+}
+
+// MustLoadString attempts to load a string and will abort with a fatal message if
+// something goes wrong
+func MustLoadString(filename string) string {
+ data, err := ioutil.ReadFile(filename)
+ if err != nil {
+ fmt.Printf("FATAL: Unable to load file '%s': %s\n", filename, err.Error())
+ os.Exit(1)
+ }
+ return *(*string)(unsafe.Pointer(&data))
+}
+
+// MD5File returns the md5sum of the given file
+func MD5File(filename string) (string, error) {
+ f, err := os.Open(filename)
+ if err != nil {
+ return "", err
+ }
+ defer f.Close()
+
+ h := md5.New()
+ if _, err := io.Copy(h, f); err != nil {
+ return "", err
+ }
+
+ return fmt.Sprintf("%x", h.Sum(nil)), nil
+}
+
+// MustMD5File will call MD5File and abort the program on error
+func MustMD5File(filename string) string {
+ result, err := MD5File(filename)
+ if err != nil {
+ println("FATAL: Unable to MD5Sum file:", err.Error())
+ os.Exit(1)
+ }
+ return result
+}
+
+// MustWriteString will attempt to write the given data to the given filename
+// It will abort the program in the event of a failure
+func MustWriteString(filename string, data string) {
+ err := ioutil.WriteFile(filename, []byte(data), 0755)
+ if err != nil {
+ fatal("Unable to write file", filename, ":", err.Error())
+ os.Exit(1)
+ }
+}
+
+// fatal will print the optional messages and die
+func fatal(message ...string) {
+ if len(message) > 0 {
+ print("FATAL:")
+ for text := range message {
+ print(text)
+ }
+ }
+ os.Exit(1)
+}
+
+// GetSubdirectories returns a list of subdirectories for the given root directory
+func GetSubdirectories(rootDir string) (*slicer.StringSlicer, error) {
+ var result slicer.StringSlicer
+
+ // Iterate root dir
+ err := filepath.Walk(rootDir, func(path string, info os.FileInfo, err error) error {
+ if err != nil {
+ return err
+ }
+ // If we have a directory, save it
+ if info.IsDir() {
+ result.Add(path)
+ }
+ return nil
+ })
+ return &result, err
+}
+
+func DirIsEmpty(dir string) (bool, error) {
+
+ // CREDIT: https://stackoverflow.com/a/30708914/8325411
+ f, err := os.Open(dir)
+ if err != nil {
+ return false, err
+ }
+ defer f.Close()
+
+ _, err = f.Readdirnames(1) // Or f.Readdir(1)
+ if err == io.EOF {
+ return true, nil
+ }
+ return false, err // Either not empty or error, suits both cases
+}
+
+// CopyDir recursively copies a directory tree, attempting to preserve permissions.
+// Source directory must exist, destination directory must *not* exist.
+// Symlinks are ignored and skipped.
+// Credit: https://gist.github.com/r0l1/92462b38df26839a3ca324697c8cba04
+func CopyDir(src string, dst string) (err error) {
+ src = filepath.Clean(src)
+ dst = filepath.Clean(dst)
+
+ si, err := os.Stat(src)
+ if err != nil {
+ return err
+ }
+ if !si.IsDir() {
+ return fmt.Errorf("source is not a directory")
+ }
+
+ _, err = os.Stat(dst)
+ if err != nil && !os.IsNotExist(err) {
+ return
+ }
+ if err == nil {
+ return fmt.Errorf("destination already exists")
+ }
+
+ err = MkDirs(dst)
+ if err != nil {
+ return
+ }
+
+ entries, err := ioutil.ReadDir(src)
+ if err != nil {
+ return
+ }
+
+ for _, entry := range entries {
+ srcPath := filepath.Join(src, entry.Name())
+ dstPath := filepath.Join(dst, entry.Name())
+
+ if entry.IsDir() {
+ err = CopyDir(srcPath, dstPath)
+ if err != nil {
+ return
+ }
+ } else {
+ // Skip symlinks.
+ if entry.Mode()&os.ModeSymlink != 0 {
+ continue
+ }
+
+ err = CopyFile(srcPath, dstPath)
+ if err != nil {
+ return
+ }
+ }
+ }
+
+ return
+}
+
+// CopyDirExtended recursively copies a directory tree, attempting to preserve permissions.
+// Source directory must exist, destination directory must *not* exist. It ignores any files or
+// directories that are given through the ignore parameter.
+// Symlinks are ignored and skipped.
+// Credit: https://gist.github.com/r0l1/92462b38df26839a3ca324697c8cba04
+func CopyDirExtended(src string, dst string, ignore []string) (err error) {
+
+ ignoreList := slicer.String(ignore)
+ src = filepath.Clean(src)
+ dst = filepath.Clean(dst)
+
+ si, err := os.Stat(src)
+ if err != nil {
+ return err
+ }
+ if !si.IsDir() {
+ return fmt.Errorf("source is not a directory")
+ }
+
+ _, err = os.Stat(dst)
+ if err != nil && !os.IsNotExist(err) {
+ return
+ }
+ if err == nil {
+ return fmt.Errorf("destination already exists")
+ }
+
+ err = MkDirs(dst)
+ if err != nil {
+ return
+ }
+
+ entries, err := ioutil.ReadDir(src)
+ if err != nil {
+ return
+ }
+
+ for _, entry := range entries {
+ if ignoreList.Contains(entry.Name()) {
+ continue
+ }
+ srcPath := filepath.Join(src, entry.Name())
+ dstPath := filepath.Join(dst, entry.Name())
+
+ if entry.IsDir() {
+ err = CopyDir(srcPath, dstPath)
+ if err != nil {
+ return
+ }
+ } else {
+ // Skip symlinks.
+ if entry.Mode()&os.ModeSymlink != 0 {
+ continue
+ }
+
+ err = CopyFile(srcPath, dstPath)
+ if err != nil {
+ return
+ }
+ }
+ }
+
+ return
+}
+
+// MoveDirExtended recursively moves a directory tree, attempting to preserve permissions.
+// Source directory must exist, destination directory must *not* exist. It ignores any files or
+// directories that are given through the ignore parameter.
+// Symlinks are ignored and skipped.
+func MoveDirExtended(src string, dst string, ignore []string) (err error) {
+
+ ignoreList := slicer.String(ignore)
+ src = filepath.Clean(src)
+ dst = filepath.Clean(dst)
+
+ si, err := os.Stat(src)
+ if err != nil {
+ return err
+ }
+ if !si.IsDir() {
+ return fmt.Errorf("source is not a directory")
+ }
+
+ _, err = os.Stat(dst)
+ if err != nil && !os.IsNotExist(err) {
+ return
+ }
+ if err == nil {
+ return fmt.Errorf("destination already exists")
+ }
+
+ err = MkDirs(dst)
+ if err != nil {
+ return
+ }
+
+ entries, err := ioutil.ReadDir(src)
+ if err != nil {
+ return
+ }
+
+ for _, entry := range entries {
+ if ignoreList.Contains(entry.Name()) {
+ continue
+ }
+ srcPath := filepath.Join(src, entry.Name())
+ dstPath := filepath.Join(dst, entry.Name())
+
+ // Skip symlinks.
+ if entry.Mode()&os.ModeSymlink != 0 {
+ continue
+ }
+
+ err := os.Rename(srcPath, dstPath)
+ if err != nil {
+ return err
+ }
+ }
+
+ return
+}
diff --git a/v2/internal/fs/fs_test.go b/v2/internal/fs/fs_test.go
new file mode 100644
index 000000000..2cc524123
--- /dev/null
+++ b/v2/internal/fs/fs_test.go
@@ -0,0 +1,31 @@
+package fs
+
+import (
+ "os"
+ "path/filepath"
+ "testing"
+
+ "github.com/matryer/is"
+)
+
+func TestRelativePath(t *testing.T) {
+
+ is := is.New(t)
+
+ cwd, err := os.Getwd()
+ is.Equal(err, nil)
+
+ // Check current directory
+ actual := RelativePath(".")
+ is.Equal(actual, cwd)
+
+ // Check 2 parameters
+ actual = RelativePath("..", "fs")
+ is.Equal(actual, cwd)
+
+ // Check 3 parameters including filename
+ actual = RelativePath("..", "fs", "fs.go")
+ expected := filepath.Join(cwd, "fs.go")
+ is.Equal(actual, expected)
+
+}
diff --git a/v2/internal/github/github.go b/v2/internal/github/github.go
new file mode 100644
index 000000000..e91b296e1
--- /dev/null
+++ b/v2/internal/github/github.go
@@ -0,0 +1,103 @@
+package github
+
+import (
+ "encoding/json"
+ "fmt"
+ "io/ioutil"
+ "net/http"
+ "sort"
+ "strings"
+)
+
+// GetVersionTags gets the list of tags on the Wails repo
+// It returns a list of sorted tags in descending order
+func GetVersionTags() ([]*SemanticVersion, error) {
+
+ result := []*SemanticVersion{}
+ var err error
+
+ resp, err := http.Get("https://api.github.com/repos/wailsapp/wails/tags")
+ if err != nil {
+ return result, err
+ }
+ body, err := ioutil.ReadAll(resp.Body)
+ if err != nil {
+ return result, err
+ }
+
+ data := []map[string]interface{}{}
+ err = json.Unmarshal(body, &data)
+ if err != nil {
+ return result, err
+ }
+
+ // Convert tag data to Version structs
+ for _, tag := range data {
+ version := tag["name"].(string)
+ if !strings.HasPrefix(version, "v2") {
+ continue
+ }
+ semver, err := NewSemanticVersion(version)
+ if err != nil {
+ return result, err
+ }
+ result = append(result, semver)
+ }
+
+ // Reverse Sort
+ sort.Sort(sort.Reverse(SemverCollection(result)))
+
+ return result, err
+}
+
+// GetLatestStableRelease gets the latest stable release on GitHub
+func GetLatestStableRelease() (result *SemanticVersion, err error) {
+
+ tags, err := GetVersionTags()
+ if err != nil {
+ return nil, err
+ }
+
+ for _, tag := range tags {
+ if tag.IsRelease() {
+ return tag, nil
+ }
+ }
+
+ return nil, fmt.Errorf("no release tag found")
+}
+
+// GetLatestPreRelease gets the latest prerelease on GitHub
+func GetLatestPreRelease() (result *SemanticVersion, err error) {
+
+ tags, err := GetVersionTags()
+ if err != nil {
+ return nil, err
+ }
+
+ for _, tag := range tags {
+ if tag.IsPreRelease() {
+ return tag, nil
+ }
+ }
+
+ return nil, fmt.Errorf("no prerelease tag found")
+}
+
+// IsValidTag returns true if the given string is a valid tag
+func IsValidTag(tagVersion string) (bool, error) {
+ if tagVersion[0] == 'v' {
+ tagVersion = tagVersion[1:]
+ }
+ tags, err := GetVersionTags()
+ if err != nil {
+ return false, err
+ }
+
+ for _, tag := range tags {
+ if tag.String() == tagVersion {
+ return true, nil
+ }
+ }
+ return false, nil
+}
diff --git a/v2/internal/github/semver.go b/v2/internal/github/semver.go
new file mode 100644
index 000000000..1cf5907fa
--- /dev/null
+++ b/v2/internal/github/semver.go
@@ -0,0 +1,106 @@
+package github
+
+import (
+ "fmt"
+
+ "github.com/Masterminds/semver"
+)
+
+// SemanticVersion is a struct containing a semantic version
+type SemanticVersion struct {
+ Version *semver.Version
+}
+
+// NewSemanticVersion creates a new SemanticVersion object with the given version string
+func NewSemanticVersion(version string) (*SemanticVersion, error) {
+ semverVersion, err := semver.NewVersion(version)
+ if err != nil {
+ return nil, err
+ }
+ return &SemanticVersion{
+ Version: semverVersion,
+ }, nil
+}
+
+// IsRelease returns true if it's a release version
+func (s *SemanticVersion) IsRelease() bool {
+ // Limit to v2
+ if s.Version.Major() != 2 {
+ return false
+ }
+ return len(s.Version.Prerelease()) == 0 && len(s.Version.Metadata()) == 0
+}
+
+// IsPreRelease returns true if it's a prerelease version
+func (s *SemanticVersion) IsPreRelease() bool {
+ // Limit to v1
+ if s.Version.Major() != 2 {
+ return false
+ }
+ return len(s.Version.Prerelease()) > 0
+}
+
+func (s *SemanticVersion) String() string {
+ return s.Version.String()
+}
+
+// IsGreaterThan returns true if this version is greater than the given version
+func (s *SemanticVersion) IsGreaterThan(version *SemanticVersion) (bool, error) {
+ // Set up new constraint
+ constraint, err := semver.NewConstraint("> " + version.Version.String())
+ if err != nil {
+ return false, err
+ }
+
+ // Check if the desired one is greater than the requested on
+ success, msgs := constraint.Validate(s.Version)
+ if !success {
+ return false, msgs[0]
+ }
+ return true, nil
+}
+
+// IsGreaterThanOrEqual returns true if this version is greater than or equal the given version
+func (s *SemanticVersion) IsGreaterThanOrEqual(version *SemanticVersion) (bool, error) {
+ // Set up new constraint
+ constraint, err := semver.NewConstraint(">= " + version.Version.String())
+ if err != nil {
+ return false, err
+ }
+
+ // Check if the desired one is greater than the requested on
+ success, msgs := constraint.Validate(s.Version)
+ if !success {
+ return false, msgs[0]
+ }
+ return true, nil
+}
+
+// MainVersion returns the main version of any version+prerelease+metadata
+// EG: MainVersion("1.2.3-pre") => "1.2.3"
+func (s *SemanticVersion) MainVersion() *SemanticVersion {
+ mainVersion := fmt.Sprintf("%d.%d.%d", s.Version.Major(), s.Version.Minor(), s.Version.Patch())
+ result, _ := NewSemanticVersion(mainVersion)
+ return result
+}
+
+// SemverCollection is a collection of SemanticVersion objects
+type SemverCollection []*SemanticVersion
+
+// Len returns the length of a collection. The number of Version instances
+// on the slice.
+func (c SemverCollection) Len() int {
+ return len(c)
+}
+
+// Less is needed for the sort interface to compare two Version objects on the
+// slice. If checks if one is less than the other.
+func (c SemverCollection) Less(i, j int) bool {
+ return c[i].Version.LessThan(c[j].Version)
+}
+
+// Swap is needed for the sort interface to replace the Version objects
+// at two different positions in the slice.
+func (c SemverCollection) Swap(i, j int) {
+ c[i], c[j] = c[j], c[i]
+}
diff --git a/v2/internal/github/semver_test.go b/v2/internal/github/semver_test.go
new file mode 100644
index 000000000..4f8f9a693
--- /dev/null
+++ b/v2/internal/github/semver_test.go
@@ -0,0 +1,32 @@
+package github
+
+import (
+ "github.com/matryer/is"
+ "testing"
+)
+
+func TestSemanticVersion_IsGreaterThan(t *testing.T) {
+ is2 := is.New(t)
+
+ alpha1, err := NewSemanticVersion("v2.0.0-alpha.1")
+ is2.NoErr(err)
+
+ beta1, err := NewSemanticVersion("v2.0.0-beta.1")
+ is2.NoErr(err)
+
+ v2, err := NewSemanticVersion("v2.0.0")
+ is2.NoErr(err)
+
+ is2.True(alpha1.IsPreRelease())
+ is2.True(beta1.IsPreRelease())
+ is2.True(!v2.IsPreRelease())
+ is2.True(v2.IsRelease())
+
+ result, err := beta1.IsGreaterThan(alpha1)
+ is2.NoErr(err)
+ is2.True(result)
+
+ result, err = v2.IsGreaterThan(beta1)
+ is2.NoErr(err)
+ is2.True(result)
+}
diff --git a/v2/internal/gomod/gomod.go b/v2/internal/gomod/gomod.go
new file mode 100644
index 000000000..c043d1e8f
--- /dev/null
+++ b/v2/internal/gomod/gomod.go
@@ -0,0 +1,79 @@
+package gomod
+
+import (
+ "fmt"
+ "github.com/Masterminds/semver"
+ "golang.org/x/mod/modfile"
+)
+
+func GetWailsVersionFromModFile(goModText []byte) (*semver.Version, error) {
+ file, err := modfile.Parse("", goModText, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ for _, req := range file.Require {
+ if req.Syntax == nil {
+ continue
+ }
+ tokenPosition := 0
+ if !req.Syntax.InBlock {
+ tokenPosition = 1
+ }
+ if req.Syntax.Token[tokenPosition] == "github.com/wailsapp/wails/v2" {
+ version := req.Syntax.Token[tokenPosition+1]
+ return semver.NewVersion(version)
+ }
+ }
+
+ return nil, nil
+}
+
+func GoModOutOfSync(goModData []byte, currentVersion string) (bool, error) {
+ gomodversion, err := GetWailsVersionFromModFile(goModData)
+ if err != nil {
+ return false, err
+ }
+ result, err := semver.NewVersion(currentVersion)
+ if err != nil || result == nil {
+ return false, fmt.Errorf("Unable to parse Wails version: %s", currentVersion)
+ }
+
+ return !gomodversion.Equal(result), nil
+}
+
+func UpdateGoModVersion(goModText []byte, currentVersion string) ([]byte, error) {
+ file, err := modfile.Parse("", goModText, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ err = file.AddRequire("github.com/wailsapp/wails/v2", currentVersion)
+ if err != nil {
+ return nil, err
+ }
+
+ // Replace
+ if len(file.Replace) == 0 {
+ return file.Format()
+ }
+
+ for _, req := range file.Replace {
+ if req.Syntax == nil {
+ continue
+ }
+ tokenPosition := 0
+ if !req.Syntax.InBlock {
+ tokenPosition = 1
+ }
+ if req.Syntax.Token[tokenPosition] == "github.com/wailsapp/wails/v2" {
+ version := req.Syntax.Token[tokenPosition+1]
+ _, err := semver.NewVersion(version)
+ if err == nil {
+ req.Syntax.Token[tokenPosition+1] = currentVersion
+ }
+ }
+ }
+
+ return file.Format()
+}
diff --git a/v2/internal/gomod/gomod_test.go b/v2/internal/gomod/gomod_test.go
new file mode 100644
index 000000000..7dc16fb34
--- /dev/null
+++ b/v2/internal/gomod/gomod_test.go
@@ -0,0 +1,603 @@
+package gomod
+
+import (
+ "github.com/Masterminds/semver"
+ "github.com/matryer/is"
+ "reflect"
+ "testing"
+)
+
+const basic string = `module changeme
+
+go 1.17
+
+require github.com/wailsapp/wails/v2 v2.0.0-beta.7
+
+require (
+ github.com/andybalholm/brotli v1.0.2 // indirect
+ github.com/davecgh/go-spew v1.1.1 // indirect
+ github.com/fasthttp/websocket v0.0.0-20200320073529-1554a54587ab // indirect
+ github.com/gabriel-vasile/mimetype v1.3.1 // indirect
+ github.com/go-ole/go-ole v1.2.5 // indirect
+ github.com/gofiber/fiber/v2 v2.17.0 // indirect
+ github.com/gofiber/websocket/v2 v2.0.8 // indirect
+ github.com/google/uuid v1.1.2 // indirect
+ github.com/imdario/mergo v0.3.12 // indirect
+ github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e // indirect
+ github.com/klauspost/compress v1.12.2 // indirect
+ github.com/leaanthony/debme v1.2.1 // indirect
+ github.com/leaanthony/go-ansi-parser v1.0.1 // indirect
+ github.com/leaanthony/go-common-file-dialog v1.0.3 // indirect
+ github.com/leaanthony/go-webview2 v0.0.0-20211007092718-65d2f028ef2d // indirect
+ github.com/leaanthony/gosod v1.0.3 // indirect
+ github.com/leaanthony/slicer v1.5.0 // indirect
+ github.com/leaanthony/typescriptify-golang-structs v0.1.7 // indirect
+ github.com/leaanthony/webview2runtime v1.1.0 // indirect
+ github.com/leaanthony/winc v0.0.0-20210921073452-54963136bf18 // indirect
+ github.com/pkg/browser v0.0.0-20210706143420-7d21f8c997e2 // indirect
+ github.com/pkg/errors v0.9.1 // indirect
+ github.com/savsgio/gotils v0.0.0-20200117113501-90175b0fbe3f // indirect
+ github.com/tkrajina/go-reflector v0.5.5 // indirect
+ github.com/valyala/bytebufferpool v1.0.0 // indirect
+ github.com/valyala/fasthttp v1.28.0 // indirect
+ github.com/valyala/tcplisten v1.0.0 // indirect
+ golang.org/x/net v0.0.0-20210510120150-4163338589ed // indirect
+ golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6 // indirect
+)
+
+//replace github.com/wailsapp/wails/v2 v2.0.0-beta.7 => C:\Users\leaan\Documents\wails-v2-beta\wails\v2
+`
+
+func TestGetWailsVersion(t *testing.T) {
+ tests := []struct {
+ name string
+ goModText []byte
+ want *semver.Version
+ wantErr bool
+ }{
+ {"basic", []byte(basic), semver.MustParse("v2.0.0-beta.7"), false},
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ got, err := GetWailsVersionFromModFile(tt.goModText)
+ if (err != nil) != tt.wantErr {
+ t.Errorf("GetWailsVersion() error = %v, wantErr %v", err, tt.wantErr)
+ return
+ }
+ if !reflect.DeepEqual(got, tt.want) {
+ t.Errorf("GetWailsVersion() got = %v, want %v", got, tt.want)
+ }
+ })
+ }
+}
+
+const basicUpdated string = `module changeme
+
+go 1.17
+
+require github.com/wailsapp/wails/v2 v2.0.0-beta.15
+
+require (
+ github.com/andybalholm/brotli v1.0.2 // indirect
+ github.com/davecgh/go-spew v1.1.1 // indirect
+ github.com/fasthttp/websocket v0.0.0-20200320073529-1554a54587ab // indirect
+ github.com/gabriel-vasile/mimetype v1.3.1 // indirect
+ github.com/go-ole/go-ole v1.2.5 // indirect
+ github.com/gofiber/fiber/v2 v2.17.0 // indirect
+ github.com/gofiber/websocket/v2 v2.0.8 // indirect
+ github.com/google/uuid v1.1.2 // indirect
+ github.com/imdario/mergo v0.3.12 // indirect
+ github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e // indirect
+ github.com/klauspost/compress v1.12.2 // indirect
+ github.com/leaanthony/debme v1.2.1 // indirect
+ github.com/leaanthony/go-ansi-parser v1.0.1 // indirect
+ github.com/leaanthony/go-common-file-dialog v1.0.3 // indirect
+ github.com/leaanthony/go-webview2 v0.0.0-20211007092718-65d2f028ef2d // indirect
+ github.com/leaanthony/gosod v1.0.3 // indirect
+ github.com/leaanthony/slicer v1.5.0 // indirect
+ github.com/leaanthony/typescriptify-golang-structs v0.1.7 // indirect
+ github.com/leaanthony/webview2runtime v1.1.0 // indirect
+ github.com/leaanthony/winc v0.0.0-20210921073452-54963136bf18 // indirect
+ github.com/pkg/browser v0.0.0-20210706143420-7d21f8c997e2 // indirect
+ github.com/pkg/errors v0.9.1 // indirect
+ github.com/savsgio/gotils v0.0.0-20200117113501-90175b0fbe3f // indirect
+ github.com/tkrajina/go-reflector v0.5.5 // indirect
+ github.com/valyala/bytebufferpool v1.0.0 // indirect
+ github.com/valyala/fasthttp v1.28.0 // indirect
+ github.com/valyala/tcplisten v1.0.0 // indirect
+ golang.org/x/net v0.0.0-20210510120150-4163338589ed // indirect
+ golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6 // indirect
+)
+
+//replace github.com/wailsapp/wails/v2 v2.0.0-beta.7 => C:\Users\leaan\Documents\wails-v2-beta\wails\v2
+`
+
+const multilineRequire = `module changeme
+
+go 1.17
+
+require (
+ github.com/wailsapp/wails/v2 v2.0.0-beta.7
+)
+require (
+ github.com/andybalholm/brotli v1.0.2 // indirect
+ github.com/davecgh/go-spew v1.1.1 // indirect
+ github.com/fasthttp/websocket v0.0.0-20200320073529-1554a54587ab // indirect
+ github.com/gabriel-vasile/mimetype v1.3.1 // indirect
+ github.com/go-ole/go-ole v1.2.5 // indirect
+ github.com/gofiber/fiber/v2 v2.17.0 // indirect
+ github.com/gofiber/websocket/v2 v2.0.8 // indirect
+ github.com/google/uuid v1.1.2 // indirect
+ github.com/imdario/mergo v0.3.12 // indirect
+ github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e // indirect
+ github.com/klauspost/compress v1.12.2 // indirect
+ github.com/leaanthony/debme v1.2.1 // indirect
+ github.com/leaanthony/go-ansi-parser v1.0.1 // indirect
+ github.com/leaanthony/go-common-file-dialog v1.0.3 // indirect
+ github.com/leaanthony/go-webview2 v0.0.0-20211007092718-65d2f028ef2d // indirect
+ github.com/leaanthony/gosod v1.0.3 // indirect
+ github.com/leaanthony/slicer v1.5.0 // indirect
+ github.com/leaanthony/typescriptify-golang-structs v0.1.7 // indirect
+ github.com/leaanthony/webview2runtime v1.1.0 // indirect
+ github.com/leaanthony/winc v0.0.0-20210921073452-54963136bf18 // indirect
+ github.com/pkg/browser v0.0.0-20210706143420-7d21f8c997e2 // indirect
+ github.com/pkg/errors v0.9.1 // indirect
+ github.com/savsgio/gotils v0.0.0-20200117113501-90175b0fbe3f // indirect
+ github.com/tkrajina/go-reflector v0.5.5 // indirect
+ github.com/valyala/bytebufferpool v1.0.0 // indirect
+ github.com/valyala/fasthttp v1.28.0 // indirect
+ github.com/valyala/tcplisten v1.0.0 // indirect
+ golang.org/x/net v0.0.0-20210510120150-4163338589ed // indirect
+ golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6 // indirect
+)
+
+//replace github.com/wailsapp/wails/v2 v2.0.0-beta.7 => C:\Users\leaan\Documents\wails-v2-beta\wails\v2
+`
+const multilineReplace = `module changeme
+
+go 1.17
+
+require (
+ github.com/wailsapp/wails/v2 v2.0.0-beta.7
+)
+require (
+ github.com/andybalholm/brotli v1.0.2 // indirect
+ github.com/davecgh/go-spew v1.1.1 // indirect
+ github.com/fasthttp/websocket v0.0.0-20200320073529-1554a54587ab // indirect
+ github.com/gabriel-vasile/mimetype v1.3.1 // indirect
+ github.com/go-ole/go-ole v1.2.5 // indirect
+ github.com/gofiber/fiber/v2 v2.17.0 // indirect
+ github.com/gofiber/websocket/v2 v2.0.8 // indirect
+ github.com/google/uuid v1.1.2 // indirect
+ github.com/imdario/mergo v0.3.12 // indirect
+ github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e // indirect
+ github.com/klauspost/compress v1.12.2 // indirect
+ github.com/leaanthony/debme v1.2.1 // indirect
+ github.com/leaanthony/go-ansi-parser v1.0.1 // indirect
+ github.com/leaanthony/go-common-file-dialog v1.0.3 // indirect
+ github.com/leaanthony/go-webview2 v0.0.0-20211007092718-65d2f028ef2d // indirect
+ github.com/leaanthony/gosod v1.0.3 // indirect
+ github.com/leaanthony/slicer v1.5.0 // indirect
+ github.com/leaanthony/typescriptify-golang-structs v0.1.7 // indirect
+ github.com/leaanthony/webview2runtime v1.1.0 // indirect
+ github.com/leaanthony/winc v0.0.0-20210921073452-54963136bf18 // indirect
+ github.com/pkg/browser v0.0.0-20210706143420-7d21f8c997e2 // indirect
+ github.com/pkg/errors v0.9.1 // indirect
+ github.com/savsgio/gotils v0.0.0-20200117113501-90175b0fbe3f // indirect
+ github.com/tkrajina/go-reflector v0.5.5 // indirect
+ github.com/valyala/bytebufferpool v1.0.0 // indirect
+ github.com/valyala/fasthttp v1.28.0 // indirect
+ github.com/valyala/tcplisten v1.0.0 // indirect
+ golang.org/x/net v0.0.0-20210510120150-4163338589ed // indirect
+ golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6 // indirect
+)
+
+replace github.com/wailsapp/wails/v2 v2.0.0-beta.7 => C:\Users\leaan\Documents\wails-v2-beta\wails\v2
+`
+
+const multilineReplaceNoVersion = `module changeme
+
+go 1.17
+
+require (
+ github.com/wailsapp/wails/v2 v2.0.0-beta.7
+)
+require (
+ github.com/andybalholm/brotli v1.0.2 // indirect
+ github.com/davecgh/go-spew v1.1.1 // indirect
+ github.com/fasthttp/websocket v0.0.0-20200320073529-1554a54587ab // indirect
+ github.com/gabriel-vasile/mimetype v1.3.1 // indirect
+ github.com/go-ole/go-ole v1.2.5 // indirect
+ github.com/gofiber/fiber/v2 v2.17.0 // indirect
+ github.com/gofiber/websocket/v2 v2.0.8 // indirect
+ github.com/google/uuid v1.1.2 // indirect
+ github.com/imdario/mergo v0.3.12 // indirect
+ github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e // indirect
+ github.com/klauspost/compress v1.12.2 // indirect
+ github.com/leaanthony/debme v1.2.1 // indirect
+ github.com/leaanthony/go-ansi-parser v1.0.1 // indirect
+ github.com/leaanthony/go-common-file-dialog v1.0.3 // indirect
+ github.com/leaanthony/go-webview2 v0.0.0-20211007092718-65d2f028ef2d // indirect
+ github.com/leaanthony/gosod v1.0.3 // indirect
+ github.com/leaanthony/slicer v1.5.0 // indirect
+ github.com/leaanthony/typescriptify-golang-structs v0.1.7 // indirect
+ github.com/leaanthony/webview2runtime v1.1.0 // indirect
+ github.com/leaanthony/winc v0.0.0-20210921073452-54963136bf18 // indirect
+ github.com/pkg/browser v0.0.0-20210706143420-7d21f8c997e2 // indirect
+ github.com/pkg/errors v0.9.1 // indirect
+ github.com/savsgio/gotils v0.0.0-20200117113501-90175b0fbe3f // indirect
+ github.com/tkrajina/go-reflector v0.5.5 // indirect
+ github.com/valyala/bytebufferpool v1.0.0 // indirect
+ github.com/valyala/fasthttp v1.28.0 // indirect
+ github.com/valyala/tcplisten v1.0.0 // indirect
+ golang.org/x/net v0.0.0-20210510120150-4163338589ed // indirect
+ golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6 // indirect
+)
+
+replace github.com/wailsapp/wails/v2 => C:\Users\leaan\Documents\wails-v2-beta\wails\v2
+`
+
+const multilineReplaceNoVersionBlock = `module changeme
+
+go 1.17
+
+require (
+ github.com/wailsapp/wails/v2 v2.0.0-beta.7
+)
+require (
+ github.com/andybalholm/brotli v1.0.2 // indirect
+ github.com/davecgh/go-spew v1.1.1 // indirect
+ github.com/fasthttp/websocket v0.0.0-20200320073529-1554a54587ab // indirect
+ github.com/gabriel-vasile/mimetype v1.3.1 // indirect
+ github.com/go-ole/go-ole v1.2.5 // indirect
+ github.com/gofiber/fiber/v2 v2.17.0 // indirect
+ github.com/gofiber/websocket/v2 v2.0.8 // indirect
+ github.com/google/uuid v1.1.2 // indirect
+ github.com/imdario/mergo v0.3.12 // indirect
+ github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e // indirect
+ github.com/klauspost/compress v1.12.2 // indirect
+ github.com/leaanthony/debme v1.2.1 // indirect
+ github.com/leaanthony/go-ansi-parser v1.0.1 // indirect
+ github.com/leaanthony/go-common-file-dialog v1.0.3 // indirect
+ github.com/leaanthony/go-webview2 v0.0.0-20211007092718-65d2f028ef2d // indirect
+ github.com/leaanthony/gosod v1.0.3 // indirect
+ github.com/leaanthony/slicer v1.5.0 // indirect
+ github.com/leaanthony/typescriptify-golang-structs v0.1.7 // indirect
+ github.com/leaanthony/webview2runtime v1.1.0 // indirect
+ github.com/leaanthony/winc v0.0.0-20210921073452-54963136bf18 // indirect
+ github.com/pkg/browser v0.0.0-20210706143420-7d21f8c997e2 // indirect
+ github.com/pkg/errors v0.9.1 // indirect
+ github.com/savsgio/gotils v0.0.0-20200117113501-90175b0fbe3f // indirect
+ github.com/tkrajina/go-reflector v0.5.5 // indirect
+ github.com/valyala/bytebufferpool v1.0.0 // indirect
+ github.com/valyala/fasthttp v1.28.0 // indirect
+ github.com/valyala/tcplisten v1.0.0 // indirect
+ golang.org/x/net v0.0.0-20210510120150-4163338589ed // indirect
+ golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6 // indirect
+)
+
+replace (
+ github.com/wailsapp/wails/v2 => C:\Users\leaan\Documents\wails-v2-beta\wails\v2
+)
+`
+
+const multilineReplaceBlock = `module changeme
+
+go 1.17
+
+require (
+ github.com/wailsapp/wails/v2 v2.0.0-beta.7
+)
+require (
+ github.com/andybalholm/brotli v1.0.2 // indirect
+ github.com/davecgh/go-spew v1.1.1 // indirect
+ github.com/fasthttp/websocket v0.0.0-20200320073529-1554a54587ab // indirect
+ github.com/gabriel-vasile/mimetype v1.3.1 // indirect
+ github.com/go-ole/go-ole v1.2.5 // indirect
+ github.com/gofiber/fiber/v2 v2.17.0 // indirect
+ github.com/gofiber/websocket/v2 v2.0.8 // indirect
+ github.com/google/uuid v1.1.2 // indirect
+ github.com/imdario/mergo v0.3.12 // indirect
+ github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e // indirect
+ github.com/klauspost/compress v1.12.2 // indirect
+ github.com/leaanthony/debme v1.2.1 // indirect
+ github.com/leaanthony/go-ansi-parser v1.0.1 // indirect
+ github.com/leaanthony/go-common-file-dialog v1.0.3 // indirect
+ github.com/leaanthony/go-webview2 v0.0.0-20211007092718-65d2f028ef2d // indirect
+ github.com/leaanthony/gosod v1.0.3 // indirect
+ github.com/leaanthony/slicer v1.5.0 // indirect
+ github.com/leaanthony/typescriptify-golang-structs v0.1.7 // indirect
+ github.com/leaanthony/webview2runtime v1.1.0 // indirect
+ github.com/leaanthony/winc v0.0.0-20210921073452-54963136bf18 // indirect
+ github.com/pkg/browser v0.0.0-20210706143420-7d21f8c997e2 // indirect
+ github.com/pkg/errors v0.9.1 // indirect
+ github.com/savsgio/gotils v0.0.0-20200117113501-90175b0fbe3f // indirect
+ github.com/tkrajina/go-reflector v0.5.5 // indirect
+ github.com/valyala/bytebufferpool v1.0.0 // indirect
+ github.com/valyala/fasthttp v1.28.0 // indirect
+ github.com/valyala/tcplisten v1.0.0 // indirect
+ golang.org/x/net v0.0.0-20210510120150-4163338589ed // indirect
+ golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6 // indirect
+)
+
+replace (
+ github.com/wailsapp/wails/v2 v2.0.0-beta.7 => C:\Users\leaan\Documents\wails-v2-beta\wails\v2
+)
+`
+
+const multilineRequireUpdated = `module changeme
+
+go 1.17
+
+require (
+ github.com/wailsapp/wails/v2 v2.0.0-beta.15
+)
+
+require (
+ github.com/andybalholm/brotli v1.0.2 // indirect
+ github.com/davecgh/go-spew v1.1.1 // indirect
+ github.com/fasthttp/websocket v0.0.0-20200320073529-1554a54587ab // indirect
+ github.com/gabriel-vasile/mimetype v1.3.1 // indirect
+ github.com/go-ole/go-ole v1.2.5 // indirect
+ github.com/gofiber/fiber/v2 v2.17.0 // indirect
+ github.com/gofiber/websocket/v2 v2.0.8 // indirect
+ github.com/google/uuid v1.1.2 // indirect
+ github.com/imdario/mergo v0.3.12 // indirect
+ github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e // indirect
+ github.com/klauspost/compress v1.12.2 // indirect
+ github.com/leaanthony/debme v1.2.1 // indirect
+ github.com/leaanthony/go-ansi-parser v1.0.1 // indirect
+ github.com/leaanthony/go-common-file-dialog v1.0.3 // indirect
+ github.com/leaanthony/go-webview2 v0.0.0-20211007092718-65d2f028ef2d // indirect
+ github.com/leaanthony/gosod v1.0.3 // indirect
+ github.com/leaanthony/slicer v1.5.0 // indirect
+ github.com/leaanthony/typescriptify-golang-structs v0.1.7 // indirect
+ github.com/leaanthony/webview2runtime v1.1.0 // indirect
+ github.com/leaanthony/winc v0.0.0-20210921073452-54963136bf18 // indirect
+ github.com/pkg/browser v0.0.0-20210706143420-7d21f8c997e2 // indirect
+ github.com/pkg/errors v0.9.1 // indirect
+ github.com/savsgio/gotils v0.0.0-20200117113501-90175b0fbe3f // indirect
+ github.com/tkrajina/go-reflector v0.5.5 // indirect
+ github.com/valyala/bytebufferpool v1.0.0 // indirect
+ github.com/valyala/fasthttp v1.28.0 // indirect
+ github.com/valyala/tcplisten v1.0.0 // indirect
+ golang.org/x/net v0.0.0-20210510120150-4163338589ed // indirect
+ golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6 // indirect
+)
+
+//replace github.com/wailsapp/wails/v2 v2.0.0-beta.7 => C:\Users\leaan\Documents\wails-v2-beta\wails\v2
+`
+
+func TestUpdateGoModVersion(t *testing.T) {
+ is2 := is.New(t)
+
+ type args struct {
+ goModText []byte
+ currentVersion string
+ }
+ tests := []struct {
+ name string
+ args args
+ want []byte
+ wantErr bool
+ }{
+ {"basic", args{[]byte(basic), "v2.0.0-beta.15"}, []byte(basicUpdated), false},
+ {"basicmultiline", args{[]byte(multilineRequire), "v2.0.0-beta.15"}, []byte(multilineRequireUpdated), false},
+ {"basicmultilinereplace", args{[]byte(multilineReplace), "v2.0.0-beta.15"}, []byte(multilineReplaceUpdated), false},
+ {"basicmultilinereplaceblock", args{[]byte(multilineReplaceBlock), "v2.0.0-beta.15"}, []byte(multilineReplaceBlockUpdated), false},
+ {"basicmultilinereplacenoversion", args{[]byte(multilineReplaceNoVersion), "v2.0.0-beta.15"}, []byte(multilineReplaceNoVersionUpdated), false},
+ {"basicmultilinereplacenoversionblock", args{[]byte(multilineReplaceNoVersionBlock), "v2.0.0-beta.15"}, []byte(multilineReplaceNoVersionBlockUpdated), false},
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ got, err := UpdateGoModVersion(tt.args.goModText, tt.args.currentVersion)
+ if (err != nil) != tt.wantErr {
+ t.Errorf("UpdateGoModVersion() error = %v, wantErr %v", err, tt.wantErr)
+ return
+ }
+ is2.Equal(got, tt.want)
+ })
+ }
+}
+
+func TestGoModOutOfSync(t *testing.T) {
+ is2 := is.New(t)
+
+ type args struct {
+ goModData []byte
+ currentVersion string
+ }
+ tests := []struct {
+ name string
+ args args
+ want bool
+ wantErr bool
+ }{
+ {"basic", args{[]byte(basic), "v2.0.0-beta.15"}, true, false},
+ {"basicmultiline", args{[]byte(multilineRequire), "v2.0.0-beta.15"}, true, false},
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ got, err := GoModOutOfSync(tt.args.goModData, tt.args.currentVersion)
+ if (err != nil) != tt.wantErr {
+ t.Errorf("GoModOutOfSync() error = %v, wantErr %v", err, tt.wantErr)
+ return
+ }
+ is2.Equal(got, tt.want)
+ })
+ }
+}
+
+const multilineReplaceUpdated = `module changeme
+
+go 1.17
+
+require (
+ github.com/wailsapp/wails/v2 v2.0.0-beta.15
+)
+
+require (
+ github.com/andybalholm/brotli v1.0.2 // indirect
+ github.com/davecgh/go-spew v1.1.1 // indirect
+ github.com/fasthttp/websocket v0.0.0-20200320073529-1554a54587ab // indirect
+ github.com/gabriel-vasile/mimetype v1.3.1 // indirect
+ github.com/go-ole/go-ole v1.2.5 // indirect
+ github.com/gofiber/fiber/v2 v2.17.0 // indirect
+ github.com/gofiber/websocket/v2 v2.0.8 // indirect
+ github.com/google/uuid v1.1.2 // indirect
+ github.com/imdario/mergo v0.3.12 // indirect
+ github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e // indirect
+ github.com/klauspost/compress v1.12.2 // indirect
+ github.com/leaanthony/debme v1.2.1 // indirect
+ github.com/leaanthony/go-ansi-parser v1.0.1 // indirect
+ github.com/leaanthony/go-common-file-dialog v1.0.3 // indirect
+ github.com/leaanthony/go-webview2 v0.0.0-20211007092718-65d2f028ef2d // indirect
+ github.com/leaanthony/gosod v1.0.3 // indirect
+ github.com/leaanthony/slicer v1.5.0 // indirect
+ github.com/leaanthony/typescriptify-golang-structs v0.1.7 // indirect
+ github.com/leaanthony/webview2runtime v1.1.0 // indirect
+ github.com/leaanthony/winc v0.0.0-20210921073452-54963136bf18 // indirect
+ github.com/pkg/browser v0.0.0-20210706143420-7d21f8c997e2 // indirect
+ github.com/pkg/errors v0.9.1 // indirect
+ github.com/savsgio/gotils v0.0.0-20200117113501-90175b0fbe3f // indirect
+ github.com/tkrajina/go-reflector v0.5.5 // indirect
+ github.com/valyala/bytebufferpool v1.0.0 // indirect
+ github.com/valyala/fasthttp v1.28.0 // indirect
+ github.com/valyala/tcplisten v1.0.0 // indirect
+ golang.org/x/net v0.0.0-20210510120150-4163338589ed // indirect
+ golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6 // indirect
+)
+
+replace github.com/wailsapp/wails/v2 v2.0.0-beta.15 => C:\Users\leaan\Documents\wails-v2-beta\wails\v2
+`
+const multilineReplaceNoVersionUpdated = `module changeme
+
+go 1.17
+
+require (
+ github.com/wailsapp/wails/v2 v2.0.0-beta.15
+)
+
+require (
+ github.com/andybalholm/brotli v1.0.2 // indirect
+ github.com/davecgh/go-spew v1.1.1 // indirect
+ github.com/fasthttp/websocket v0.0.0-20200320073529-1554a54587ab // indirect
+ github.com/gabriel-vasile/mimetype v1.3.1 // indirect
+ github.com/go-ole/go-ole v1.2.5 // indirect
+ github.com/gofiber/fiber/v2 v2.17.0 // indirect
+ github.com/gofiber/websocket/v2 v2.0.8 // indirect
+ github.com/google/uuid v1.1.2 // indirect
+ github.com/imdario/mergo v0.3.12 // indirect
+ github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e // indirect
+ github.com/klauspost/compress v1.12.2 // indirect
+ github.com/leaanthony/debme v1.2.1 // indirect
+ github.com/leaanthony/go-ansi-parser v1.0.1 // indirect
+ github.com/leaanthony/go-common-file-dialog v1.0.3 // indirect
+ github.com/leaanthony/go-webview2 v0.0.0-20211007092718-65d2f028ef2d // indirect
+ github.com/leaanthony/gosod v1.0.3 // indirect
+ github.com/leaanthony/slicer v1.5.0 // indirect
+ github.com/leaanthony/typescriptify-golang-structs v0.1.7 // indirect
+ github.com/leaanthony/webview2runtime v1.1.0 // indirect
+ github.com/leaanthony/winc v0.0.0-20210921073452-54963136bf18 // indirect
+ github.com/pkg/browser v0.0.0-20210706143420-7d21f8c997e2 // indirect
+ github.com/pkg/errors v0.9.1 // indirect
+ github.com/savsgio/gotils v0.0.0-20200117113501-90175b0fbe3f // indirect
+ github.com/tkrajina/go-reflector v0.5.5 // indirect
+ github.com/valyala/bytebufferpool v1.0.0 // indirect
+ github.com/valyala/fasthttp v1.28.0 // indirect
+ github.com/valyala/tcplisten v1.0.0 // indirect
+ golang.org/x/net v0.0.0-20210510120150-4163338589ed // indirect
+ golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6 // indirect
+)
+
+replace github.com/wailsapp/wails/v2 => C:\Users\leaan\Documents\wails-v2-beta\wails\v2
+`
+const multilineReplaceNoVersionBlockUpdated = `module changeme
+
+go 1.17
+
+require (
+ github.com/wailsapp/wails/v2 v2.0.0-beta.15
+)
+
+require (
+ github.com/andybalholm/brotli v1.0.2 // indirect
+ github.com/davecgh/go-spew v1.1.1 // indirect
+ github.com/fasthttp/websocket v0.0.0-20200320073529-1554a54587ab // indirect
+ github.com/gabriel-vasile/mimetype v1.3.1 // indirect
+ github.com/go-ole/go-ole v1.2.5 // indirect
+ github.com/gofiber/fiber/v2 v2.17.0 // indirect
+ github.com/gofiber/websocket/v2 v2.0.8 // indirect
+ github.com/google/uuid v1.1.2 // indirect
+ github.com/imdario/mergo v0.3.12 // indirect
+ github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e // indirect
+ github.com/klauspost/compress v1.12.2 // indirect
+ github.com/leaanthony/debme v1.2.1 // indirect
+ github.com/leaanthony/go-ansi-parser v1.0.1 // indirect
+ github.com/leaanthony/go-common-file-dialog v1.0.3 // indirect
+ github.com/leaanthony/go-webview2 v0.0.0-20211007092718-65d2f028ef2d // indirect
+ github.com/leaanthony/gosod v1.0.3 // indirect
+ github.com/leaanthony/slicer v1.5.0 // indirect
+ github.com/leaanthony/typescriptify-golang-structs v0.1.7 // indirect
+ github.com/leaanthony/webview2runtime v1.1.0 // indirect
+ github.com/leaanthony/winc v0.0.0-20210921073452-54963136bf18 // indirect
+ github.com/pkg/browser v0.0.0-20210706143420-7d21f8c997e2 // indirect
+ github.com/pkg/errors v0.9.1 // indirect
+ github.com/savsgio/gotils v0.0.0-20200117113501-90175b0fbe3f // indirect
+ github.com/tkrajina/go-reflector v0.5.5 // indirect
+ github.com/valyala/bytebufferpool v1.0.0 // indirect
+ github.com/valyala/fasthttp v1.28.0 // indirect
+ github.com/valyala/tcplisten v1.0.0 // indirect
+ golang.org/x/net v0.0.0-20210510120150-4163338589ed // indirect
+ golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6 // indirect
+)
+
+replace (
+ github.com/wailsapp/wails/v2 => C:\Users\leaan\Documents\wails-v2-beta\wails\v2
+)
+`
+
+const multilineReplaceBlockUpdated = `module changeme
+
+go 1.17
+
+require (
+ github.com/wailsapp/wails/v2 v2.0.0-beta.15
+)
+
+require (
+ github.com/andybalholm/brotli v1.0.2 // indirect
+ github.com/davecgh/go-spew v1.1.1 // indirect
+ github.com/fasthttp/websocket v0.0.0-20200320073529-1554a54587ab // indirect
+ github.com/gabriel-vasile/mimetype v1.3.1 // indirect
+ github.com/go-ole/go-ole v1.2.5 // indirect
+ github.com/gofiber/fiber/v2 v2.17.0 // indirect
+ github.com/gofiber/websocket/v2 v2.0.8 // indirect
+ github.com/google/uuid v1.1.2 // indirect
+ github.com/imdario/mergo v0.3.12 // indirect
+ github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e // indirect
+ github.com/klauspost/compress v1.12.2 // indirect
+ github.com/leaanthony/debme v1.2.1 // indirect
+ github.com/leaanthony/go-ansi-parser v1.0.1 // indirect
+ github.com/leaanthony/go-common-file-dialog v1.0.3 // indirect
+ github.com/leaanthony/go-webview2 v0.0.0-20211007092718-65d2f028ef2d // indirect
+ github.com/leaanthony/gosod v1.0.3 // indirect
+ github.com/leaanthony/slicer v1.5.0 // indirect
+ github.com/leaanthony/typescriptify-golang-structs v0.1.7 // indirect
+ github.com/leaanthony/webview2runtime v1.1.0 // indirect
+ github.com/leaanthony/winc v0.0.0-20210921073452-54963136bf18 // indirect
+ github.com/pkg/browser v0.0.0-20210706143420-7d21f8c997e2 // indirect
+ github.com/pkg/errors v0.9.1 // indirect
+ github.com/savsgio/gotils v0.0.0-20200117113501-90175b0fbe3f // indirect
+ github.com/tkrajina/go-reflector v0.5.5 // indirect
+ github.com/valyala/bytebufferpool v1.0.0 // indirect
+ github.com/valyala/fasthttp v1.28.0 // indirect
+ github.com/valyala/tcplisten v1.0.0 // indirect
+ golang.org/x/net v0.0.0-20210510120150-4163338589ed // indirect
+ golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6 // indirect
+)
+
+replace (
+ github.com/wailsapp/wails/v2 v2.0.0-beta.15 => C:\Users\leaan\Documents\wails-v2-beta\wails\v2
+)
+`
diff --git a/v2/internal/html/asset.go b/v2/internal/html/asset.go
new file mode 100644
index 000000000..4c41358f4
--- /dev/null
+++ b/v2/internal/html/asset.go
@@ -0,0 +1,128 @@
+package html
+
+import (
+ "fmt"
+ "io/ioutil"
+ "log"
+ "net/url"
+ "path/filepath"
+ "regexp"
+ "strings"
+ "unsafe"
+
+ "github.com/tdewolff/minify"
+ "github.com/tdewolff/minify/js"
+)
+
+type assetTypes struct {
+ JS string
+ CSS string
+ FAVICON string
+ HTML string
+}
+
+// AssetTypes is an enum for the asset type keys
+var AssetTypes *assetTypes = &assetTypes{
+ JS: "javascript",
+ CSS: "css",
+ FAVICON: "favicon",
+ HTML: "html",
+}
+
+// Asset describes an asset type and its path
+type Asset struct {
+ Type string
+ Path string
+ Data string
+}
+
+// Load the asset from disk
+func (a *Asset) Load(basedirectory string) error {
+ assetpath := filepath.Join(basedirectory, a.Path)
+ data, err := ioutil.ReadFile(assetpath)
+ if err != nil {
+ return err
+ }
+ a.Data = string(data)
+ return nil
+}
+
+// AsString returns the data as a READ ONLY string
+func (a *Asset) AsString() string {
+ return a.Data
+}
+
+func (a *Asset) minifiedData() (string, error) {
+ switch a.Type {
+ case AssetTypes.HTML:
+
+ // Escape HTML
+ var re = regexp.MustCompile(`[\s]+`)
+ result := re.ReplaceAllString(a.Data, ` `)
+
+ // Inject wailsloader code
+ result = strings.Replace(result, `
+
+ `, ``, 1)
+
+ url := url.URL{Path: result}
+ urlString := strings.ReplaceAll(url.String(), "/", "%2f")
+
+ // Save Data uRI string
+ return "data:text/html;charset=utf-8," + urlString, nil
+
+ case AssetTypes.CSS:
+
+ // Escape CSS data
+ var re = regexp.MustCompile(`\s{2,}`)
+ result := re.ReplaceAllString(a.Data, ``)
+ result = strings.ReplaceAll(result, "\n", "")
+ result = strings.ReplaceAll(result, "\r\n", "")
+ result = strings.ReplaceAll(result, "\n", "")
+ result = strings.ReplaceAll(result, "\t", "")
+ result = strings.ReplaceAll(result, `\`, `\\`)
+ result = strings.ReplaceAll(result, `"`, `\"`)
+ result = strings.ReplaceAll(result, `'`, `\'`)
+ result = strings.ReplaceAll(result, ` {`, `{`)
+ result = strings.ReplaceAll(result, `: `, `:`)
+ return fmt.Sprintf("window.wails._.InjectCSS(\"%s\");", result), nil
+
+ case AssetTypes.JS:
+ m := minify.New()
+ m.AddFunc("application/javascript", js.Minify)
+ var err error
+ result, err := m.String("application/javascript", a.Data+";")
+ if err != nil {
+ return "", err
+ }
+ return result, nil
+ default:
+ return "", fmt.Errorf("minification for asset type %s not implemented", a.Type)
+ }
+}
+
+// AsCHexData processes the asset data so it may be used by C
+func (a *Asset) AsCHexData() string {
+ dataString, err := a.minifiedData()
+ if err != nil {
+ log.Fatal(err)
+ }
+ // Get byte data of the string
+ bytes := *(*[]byte)(unsafe.Pointer(&dataString))
+
+ // Create a strings builder
+ var cdata strings.Builder
+
+ // Set buffer size to 4k
+ cdata.Grow(4096)
+
+ // Convert each byte to hex
+ for _, b := range bytes {
+ cdata.WriteString(fmt.Sprintf("0x%x, ", b))
+ }
+
+ return cdata.String()
+}
+
+// Dump will output the asset to the terminal
+func (a *Asset) Dump() {
+ fmt.Printf("{ Type: %s, Path: %s, Data: %+v }\n", a.Type, a.Path, a.Data[:10])
+}
diff --git a/v2/internal/html/asset_test.go b/v2/internal/html/asset_test.go
new file mode 100644
index 000000000..f743b4ba9
--- /dev/null
+++ b/v2/internal/html/asset_test.go
@@ -0,0 +1,53 @@
+package html
+
+import "testing"
+
+func TestAsset_minifiedData(t *testing.T) {
+ type fields struct {
+ Type string
+ Path string
+ Data string
+ }
+ tests := []struct {
+ name string
+ fields fields
+ want string
+ wantErr bool
+ }{
+ {
+ name: "multi-line tag",
+ fields: fields{
+ Type: AssetTypes.HTML,
+ Path: "foo.html",
+ Data: " \n",
+ },
+ want: "data:text/html;charset=utf-8,%3Clink%20rel=%22stylesheet%22%20href=%22src%2ffoo.css%22%20%3E%20",
+ },
+ {
+ name: "multi-line tag no spaces",
+ fields: fields{
+ Type: AssetTypes.HTML,
+ Path: "foo.html",
+ Data: " \n",
+ },
+ want: "data:text/html;charset=utf-8,%3Clink%20rel=%22stylesheet%22%20href=%22src%2ffoo.css%22%20%3E%20",
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ a := &Asset{
+ Type: tt.fields.Type,
+ Path: tt.fields.Path,
+ Data: tt.fields.Data,
+ }
+ got, err := a.minifiedData()
+ if (err != nil) != tt.wantErr {
+ t.Errorf("Asset.minifiedData() error = %v, wantErr %v", err, tt.wantErr)
+ return
+ }
+ if got != tt.want {
+ t.Errorf("Asset.minifiedData() = %v, want %v", got, tt.want)
+ }
+ })
+ }
+}
diff --git a/v2/internal/html/assetbundle.go b/v2/internal/html/assetbundle.go
new file mode 100644
index 000000000..6ec098c7e
--- /dev/null
+++ b/v2/internal/html/assetbundle.go
@@ -0,0 +1,218 @@
+package html
+
+import (
+ "bytes"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "path/filepath"
+ "strings"
+
+ "github.com/leaanthony/slicer"
+ "github.com/wailsapp/wails/v2/internal/assetdb"
+ "golang.org/x/net/html"
+)
+
+// AssetBundle is a collection of Assets
+type AssetBundle struct {
+ assets []*Asset
+ basedirectory string
+}
+
+// NewAssetBundle creates a new AssetBundle struct containing
+// the given html and all the assets referenced by it
+func NewAssetBundle(pathToHTML string) (*AssetBundle, error) {
+
+ // Create result
+ result := &AssetBundle{
+ basedirectory: filepath.Dir(pathToHTML),
+ }
+
+ err := result.loadAssets(pathToHTML)
+ if err != nil {
+ return nil, err
+ }
+
+ return result, nil
+}
+
+// loadAssets processes the given html file and loads in
+// all referenced assets
+func (a *AssetBundle) loadAssets(pathToHTML string) error {
+
+ // Save HTML
+ htmlAsset := &Asset{
+ Type: AssetTypes.HTML,
+ Path: filepath.Base(pathToHTML),
+ }
+ err := htmlAsset.Load(a.basedirectory)
+ if err != nil {
+ return err
+ }
+ a.assets = append(a.assets, htmlAsset)
+
+ return a.processHTML(htmlAsset.AsString())
+}
+
+// Credit to: https://drstearns.github.io/tutorials/tokenizing/
+func (a *AssetBundle) processHTML(htmldata string) error {
+
+ // Tokenize the html
+ buf := bytes.NewBufferString(htmldata)
+ tokenizer := html.NewTokenizer(buf)
+
+ paths := slicer.String()
+
+ for {
+ //get the next token type
+ tokenType := tokenizer.Next()
+
+ //if it's an error token, we either reached
+ //the end of the file, or the HTML was malformed
+ if tokenType == html.ErrorToken {
+ err := tokenizer.Err()
+ if err == io.EOF {
+ //end of the file, break out of the loop
+ break
+ }
+ //otherwise, there was an error tokenizing,
+ //which likely means the HTML was malformed.
+ //since this is a simple command-line utility,
+ //we can just use log.Fatalf() to report the error
+ //and exit the process with a non-zero status code
+ return tokenizer.Err()
+ }
+
+ //process the token according to the token type...
+ if tokenType == html.StartTagToken || tokenType == html.SelfClosingTagToken {
+ //get the token
+ token := tokenizer.Token()
+
+ //if the name of the element is "title"
+ if "link" == token.Data {
+ //the next token should be the page title
+ tokenType = tokenizer.Next()
+ //just make sure it's actually a text token
+ asset := &Asset{}
+ for _, attr := range token.Attr {
+ // Favicon
+ if attr.Key == "rel" && attr.Val == "icon" {
+ asset.Type = AssetTypes.FAVICON
+ }
+ if attr.Key == "href" {
+ asset.Path = attr.Val
+ }
+ // standard stylesheet
+ if attr.Key == "rel" && attr.Val == "stylesheet" {
+ asset.Type = AssetTypes.CSS
+ }
+ if attr.Key == "as" && attr.Val == "style" {
+ asset.Type = AssetTypes.CSS
+ }
+ if attr.Key == "as" && attr.Val == "script" {
+ asset.Type = AssetTypes.JS
+ }
+ if attr.Key == "rel" && attr.Val == "modulepreload" {
+ asset.Type = AssetTypes.JS
+ }
+ }
+
+ // Ensure we don't include duplicates
+ if !paths.Contains(asset.Path) {
+ err := asset.Load(a.basedirectory)
+ if err != nil {
+ return err
+ }
+ a.assets = append(a.assets, asset)
+ paths.Add(asset.Path)
+ }
+ }
+ if "script" == token.Data {
+ tokenType = tokenizer.Next()
+ //just make sure it's actually a text token
+ asset := &Asset{Type: AssetTypes.JS}
+ for _, attr := range token.Attr {
+ if attr.Key == "src" {
+ asset.Path = attr.Val
+ break
+ }
+ }
+ if !paths.Contains(asset.Path) && asset.Path != "" {
+ err := asset.Load(a.basedirectory)
+ if err != nil {
+ return err
+ }
+ a.assets = append(a.assets, asset)
+ paths.Add(asset.Path)
+ }
+ }
+ }
+ }
+
+ return nil
+}
+
+// WriteToCFile dumps all the assets to C files in the given directory
+func (a *AssetBundle) WriteToCFile(targetDir string) (string, error) {
+
+ // Write out the assets.c file
+ var cdata strings.Builder
+
+ // Write header
+ header := `// assets.h
+// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL.
+// This file was auto-generated. DO NOT MODIFY.
+
+`
+ cdata.WriteString(header)
+
+ // Loop over the Assets
+ var err error
+ assetVariables := slicer.String()
+ var variableName string
+ for index, asset := range a.assets {
+ // For desktop we ignore the favicon
+ if asset.Type == AssetTypes.FAVICON {
+ continue
+ }
+ variableName = fmt.Sprintf("%s%d", asset.Type, index)
+ assetCdata := fmt.Sprintf("const unsigned char %s[]={ %s0x00 };\n", variableName, asset.AsCHexData())
+ cdata.WriteString(assetCdata)
+ assetVariables.Add(variableName)
+ }
+
+ if assetVariables.Length() > 0 {
+ cdata.WriteString(fmt.Sprintf("\nconst unsigned char *assets[] = { %s, 0x00 };", assetVariables.Join(", ")))
+ } else {
+ cdata.WriteString("\nconst unsigned char *assets[] = { 0x00 };")
+ }
+
+ // Save file
+ assetsFile := filepath.Join(targetDir, "assets.h")
+ err = ioutil.WriteFile(assetsFile, []byte(cdata.String()), 0600)
+ if err != nil {
+ return "", err
+ }
+ return assetsFile, nil
+}
+
+// ConvertToAssetDB returns an assetdb.AssetDB initialized with
+// the items in the AssetBundle
+func (a *AssetBundle) ConvertToAssetDB() (*assetdb.AssetDB, error) {
+ theassetdb := assetdb.NewAssetDB()
+
+ // Loop over the Assets
+ for _, asset := range a.assets {
+ theassetdb.AddAsset(asset.Path, []byte(asset.Data))
+ }
+
+ return theassetdb, nil
+}
+
+// Dump will output the assets to the terminal
+func (a *AssetBundle) Dump() {
+ println("Assets:")
+ for _, asset := range a.assets {
+ asset.Dump()
+ }
+}
diff --git a/v2/internal/html/assetbundle_test.go b/v2/internal/html/assetbundle_test.go
new file mode 100644
index 000000000..d1009d7ac
--- /dev/null
+++ b/v2/internal/html/assetbundle_test.go
@@ -0,0 +1,84 @@
+package html
+
+import (
+ "testing"
+)
+
+func TestNewAssetBundle(t *testing.T) {
+ tests := []struct {
+ name string
+ pathToHTML string
+ wantAssets []string
+ wantErr bool
+ }{
+ {
+ name: "basic html",
+ pathToHTML: "testdata/basic.html",
+ wantAssets: []string{
+ AssetTypes.HTML,
+ AssetTypes.FAVICON,
+ AssetTypes.JS,
+ AssetTypes.CSS,
+ },
+ wantErr: false,
+ },
+ {
+ name: "self closing tags",
+ pathToHTML: "testdata/self_closing.html",
+ wantAssets: []string{
+ AssetTypes.HTML,
+ AssetTypes.FAVICON,
+ AssetTypes.JS,
+ AssetTypes.CSS,
+ },
+ wantErr: false,
+ },
+ {
+ name: "multi-line tags",
+ pathToHTML: "testdata/self_closing.html",
+ wantAssets: []string{
+ AssetTypes.HTML,
+ AssetTypes.FAVICON,
+ AssetTypes.JS,
+ AssetTypes.CSS,
+ },
+ wantErr: false,
+ },
+ {
+ name: "inline javascript",
+ pathToHTML: "testdata/inline_javascript.html",
+ wantAssets: []string{
+ AssetTypes.HTML,
+ AssetTypes.FAVICON,
+ AssetTypes.JS,
+ AssetTypes.CSS,
+ },
+ wantErr: false,
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ got, err := NewAssetBundle(tt.pathToHTML)
+ if (err != nil) != tt.wantErr {
+ t.Errorf("NewAssetBundle() error = %v, wantErr %v", err, tt.wantErr)
+ return
+ }
+ if len(got.assets) != len(tt.wantAssets) {
+ t.Errorf("NewAssetBundle() len(assets) = %d, want %d",
+ len(got.assets), len(tt.wantAssets))
+ }
+
+ for i := range tt.wantAssets {
+ if i >= len(got.assets) {
+ t.Errorf("NewAssetBundle() missing assets[%d].Type = %s",
+ i, tt.wantAssets[i])
+ } else {
+ if got.assets[i].Type != tt.wantAssets[i] {
+ t.Errorf("NewAssetBundle() assets[%d].Type = %s, want %s",
+ i, got.assets[i].Type, tt.wantAssets[i])
+ }
+ }
+ }
+ })
+ }
+}
diff --git a/v2/internal/html/testdata/basic.html b/v2/internal/html/testdata/basic.html
new file mode 100644
index 000000000..cdc3770b8
--- /dev/null
+++ b/v2/internal/html/testdata/basic.html
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
Vite App
+
+
+