Compare commits

...

41 Commits

Author SHA1 Message Date
Travis McLane
319fd9ec82 hack: enable builds on non-Windows 2021-05-07 16:05:15 -04:00
Alexander Hudek
6b8370daad Implement server to client notify support. (#700) 2021-05-02 13:13:18 +10:00
Alexander Hudek
3c4f874db5 Implement server to client notify support. (#700) 2021-05-02 13:12:29 +10:00
Alexander Hudek
0966c96ef0 Fixed generated typescript type for []byte. (#701) 2021-05-02 13:08:49 +10:00
Lea Anthony
6b919808c9 [windows] Added options, WindowBackgroundIsTranslucent 2021-05-02 12:04:29 +10:00
Lea Anthony
590d4fcdbb [windows] Updated WebView2 to Microsoft.Web.WebView2.1.0.818.41 2021-05-02 11:13:27 +10:00
Lea Anthony
4acb3f83bf [windows] Support Startup hook 2021-05-01 07:38:30 +10:00
Lea Anthony
df32393215 [windows] Make initial loading a sync operation 2021-05-01 07:20:36 +10:00
Lea Anthony
ff3e03220e [windows] Backend calls now working 2021-05-01 06:44:07 +10:00
Lea Anthony
5da198de7e [windows] App assets loading correctly 2021-04-30 21:14:09 +10:00
Lea Anthony
247df54ef0 update vanilla template css 2021-04-30 17:44:40 +10:00
Lea Anthony
161eeca62b [windows] update eslint ecmaversion 2021-04-30 16:05:29 +10:00
Lea Anthony
0b8056bcf4 [windows] Windows runtime 2021-04-30 16:04:24 +10:00
Lea Anthony
62bfe953a1 [windows] Add CGO_CXXFLAGS 2021-04-30 16:00:09 +10:00
Lea Anthony
67611d5ae7 [windows] Support -compress flag for UPX compression 2021-04-29 21:53:17 +10:00
Lea Anthony
77b5235c9f [windows] Compressed DLLs 2021-04-29 21:36:26 +10:00
Lea Anthony
09755d5bfe [windows] Adjust when resizing 2021-04-29 21:25:20 +10:00
Lea Anthony
0224228c46 [windows] Add DPI awareness 2021-04-29 21:25:03 +10:00
Lea Anthony
168cd96f56 Fix some warnings 2021-04-29 07:36:59 +10:00
Lea Anthony
6f6e810432 [windows] WebView2 component working 2021-04-29 07:36:40 +10:00
Lea Anthony
944e1c99ff [windows] Closer to webview2 integration 2021-04-28 15:45:36 +10:00
Lea Anthony
7f54f7bb7e fix frameless option 2021-04-28 15:44:55 +10:00
Lea Anthony
2881a5bc0d [windows] output required DLLs on build 2021-04-28 15:44:29 +10:00
Lea Anthony
ee05884c9c [windows] ON_MAIN_THEAD macro. Misc updates 2021-04-27 21:09:04 +10:00
Lea Anthony
385988989b fix: min/max constraint logic 2021-04-27 19:32:25 +10:00
Lea Anthony
b98c7dd49f [windows] Move to C++. Support unicode titles. Add test. 2021-04-26 20:21:11 +10:00
Lea Anthony
b3c0cc86d3 Merge remote-tracking branch 'origin/v2-alpha' into v2-alpha 2021-04-26 19:09:04 +10:00
Lea Anthony
ad34e55a67 [windows] wrap ffenestri.h for c++ 2021-04-26 18:55:04 +10:00
Lea Anthony
1bdbf68ca9 [windows] Main thread dispatcher. Small refactor. 2021-04-26 07:14:24 +10:00
Lea Anthony
84f37c66ba [windows] Center 2021-04-25 21:16:27 +10:00
Lea Anthony
f7c65b1705 [windows] Show,Hide,Maximise,Minimise,Unmaximise,Unminimise,ToggleMaximise,ToggleMinimise 2021-04-25 15:53:48 +10:00
Lea Anthony
134b41e4be [windows] StartHidden 2021-04-25 15:27:09 +10:00
Lea Anthony
df41e8eb3a [windows] DisableResize 2021-04-25 15:20:30 +10:00
Lea Anthony
0f668a9038 Min/Max size + setTitle 2021-04-25 15:03:14 +10:00
Lea Anthony
dea6d261ad Ensure min/max window sizes are valid 2021-04-25 14:52:42 +10:00
Lea Anthony
97592fad5c [win] Initial window working 2021-04-24 20:59:00 +10:00
Lea Anthony
8caf277bf1 v2.0.0-alpha.65 2021-04-20 19:44:27 +10:00
Lea Anthony
4b480bb085 Move templates to CLI dir. Use go:embed 2021-04-18 17:10:12 +10:00
Lea Anthony
c1d63aff34 Refactor vanilla template to work with wails dev out of the box 2021-04-18 07:25:02 +10:00
Lea Anthony
5fc89c4cad Fix Promise<void> return type. Tidy up. 2021-04-18 07:24:29 +10:00
Lea Anthony
5e96bb5a32 [windows] Improve wails doctor 2021-04-17 13:40:27 +10:00
66 changed files with 14435 additions and 234 deletions

2
.gitignore vendored
View File

@@ -27,3 +27,5 @@ v2/pkg/parser/testproject/frontend/wails
v2/test/kitchensink/frontend/public
v2/test/kitchensink/build/darwin/desktop/kitchensink
v2/test/kitchensink/frontend/package.json.md5
/v2/internal/ffenestri/windows/test/cmake-build-debug/
.idea/

View File

@@ -24,10 +24,6 @@ func AddBuildSubcommand(app *clir.Cli, w io.Writer) {
command := app.NewSubCommand("build", "Builds the application")
// Setup target type flag
//description := "Type of application to build. Valid types: " + validTargetTypes.Join(",")
//command.StringFlag("t", description, &outputType)
// Setup production flag
production := false
command.BoolFlag("production", "Build in production mode", &production)
@@ -58,10 +54,6 @@ func AddBuildSubcommand(app *clir.Cli, w io.Writer) {
tags := ""
command.StringFlag("tags", "tags to pass to Go compiler (quoted and space separated)", &tags)
// Log to file
//logFile := ""
//command.StringFlag("l", "Log to file", &logFile)
// Retain assets
keepAssets := false
command.BoolFlag("k", "Keep generated assets", &keepAssets)
@@ -74,11 +66,6 @@ func AddBuildSubcommand(app *clir.Cli, w io.Writer) {
cleanBuildDirectory := false
command.BoolFlag("clean", "Clean the build directory before building", &cleanBuildDirectory)
appleIdentity := ""
if runtime.GOOS == "darwin" {
command.StringFlag("sign", "Signs your app with the given identity.", &appleIdentity)
}
command.Action(func() error {
quiet := verbosity == 0
@@ -96,11 +83,6 @@ func AddBuildSubcommand(app *clir.Cli, w io.Writer) {
app.PrintBanner()
}
// Ensure package is used with apple identity
if appleIdentity != "" && pack == false {
return fmt.Errorf("must use `-package` flag when using `-sign`")
}
// Setup mode
mode := build.Debug
if production {
@@ -115,7 +97,8 @@ func AddBuildSubcommand(app *clir.Cli, w io.Writer) {
"darwin/universal",
//"linux/amd64",
//"linux/arm-7",
//"windows/amd64",
"windows",
"windows/amd64",
})
if !validPlatformArch.Contains(platform) {
return fmt.Errorf("platform %s is not supported", platform)
@@ -146,7 +129,6 @@ func AddBuildSubcommand(app *clir.Cli, w io.Writer) {
LDFlags: ldflags,
Compiler: compilerCommand,
KeepAssets: keepAssets,
AppleIdentity: appleIdentity,
Verbosity: verbosity,
Compress: compress,
UserTags: userTags,

View File

@@ -48,9 +48,7 @@ func AddSubcommand(app *clir.Cli, w io.Writer) error {
// Exit early if PM not found
if info.PM == nil {
fmt.Fprintf(w, "\n%s\t%s", "Package Manager:", "Not Found")
w.Flush()
println()
return nil
}
fmt.Fprintf(w, "%s\t%s\n", "Package Manager: ", info.PM.Name())

View File

@@ -9,7 +9,7 @@ import (
"github.com/wailsapp/wails/v2/pkg/parser"
)
// AddSubcommand adds the `dev` command for the Wails application
// 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")
@@ -19,7 +19,7 @@ func AddSubcommand(app *clir.Cli, w io.Writer) error {
// Quiet Init
quiet := false
backendAPI.BoolFlag("q", "Supress output to console", &quiet)
backendAPI.BoolFlag("q", "Suppress output to console", &quiet)
backendAPI.Action(func() error {
@@ -85,7 +85,4 @@ func logPackage(pkg *parser.Package, logger *clilogger.CLILogger) {
}
}
logger.Println("")
// logger.Println(" Original Go Package Path:", pkg.Gopackage.PkgPath)
// logger.Println(" Original Go Package Path:", pkg.Gopackage.PkgPath)
}

View File

@@ -6,9 +6,10 @@ import (
"strings"
"time"
"github.com/wailsapp/wails/v2/cmd/wails/internal/commands/initialise/templates"
"github.com/leaanthony/clir"
"github.com/pkg/errors"
"github.com/wailsapp/wails/v2/internal/templates"
"github.com/wailsapp/wails/v2/pkg/clilogger"
"github.com/wailsapp/wails/v2/pkg/git"
)

View File

@@ -1,14 +1,16 @@
package templates
import (
"embed"
"encoding/json"
"fmt"
"io/ioutil"
gofs "io/fs"
"os"
"path/filepath"
"runtime"
"strings"
"github.com/leaanthony/debme"
"github.com/leaanthony/gosod"
"github.com/leaanthony/slicer"
"github.com/olekukonko/tablewriter"
@@ -16,6 +18,12 @@ import (
"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
@@ -59,20 +67,21 @@ type Template struct {
HelpURL string `json:"helpurl"`
// Other data
Directory string `json:"-"`
FS gofs.FS `json:"-"`
}
func parseTemplate(directory string) (Template, error) {
templateJSON := filepath.Join(directory, "template.json")
func parseTemplate(template gofs.FS) (Template, error) {
var result Template
data, err := ioutil.ReadFile(templateJSON)
data, err := gofs.ReadFile(template, "template.json")
if err != nil {
return result, err
}
result.Directory = directory
err = json.Unmarshal(data, &result)
return result, err
if err != nil {
return result, err
}
result.FS = template
return result, nil
}
// TemplateShortNames returns a slicer of short template names
@@ -134,11 +143,13 @@ func getTemplateByShortname(shortname string) (Template, error) {
// Loads the template cache
func loadTemplateCache() error {
// Get local template directory
templateDir := fs.RelativePath("templates")
templatesFS, err := debme.FS(templates, "templates")
if err != nil {
return err
}
// Get directories
files, err := ioutil.ReadDir(templateDir)
files, err := templatesFS.ReadDir(".")
if err != nil {
return err
}
@@ -148,8 +159,11 @@ func loadTemplateCache() error {
for _, file := range files {
if file.IsDir() {
templateDir := filepath.Join(templateDir, file.Name())
template, err := parseTemplate(templateDir)
templateFS, err := templatesFS.FS(file.Name())
if err != nil {
return err
}
template, err := parseTemplate(templateFS)
if err != nil {
// Cannot parse this template, continue
continue
@@ -163,7 +177,6 @@ func loadTemplateCache() error {
// Install the given template
func Install(options *Options) error {
// Get cwd
cwd, err := os.Getwd()
if err != nil {
@@ -211,19 +224,16 @@ func Install(options *Options) error {
}
// Use Gosod to install the template
installer, err := gosod.TemplateDir(template.Directory)
if err != nil {
return err
}
installer := gosod.New(template.FS)
// Ignore template.json files
installer.IgnoreFilename("template.json")
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("../..")
localWailsDirectory := fs.RelativePath("../../../../../..")
templateData := &Data{
ProjectName: options.ProjectName,
BinaryName: filepath.Base(options.TargetDir),
@@ -295,14 +305,14 @@ func generateIDEFiles(options *Options) error {
func generateVSCodeFiles(options *Options) error {
targetDir := filepath.Join(options.TargetDir, ".vscode")
sourceDir := fs.RelativePath(filepath.Join("./ides/vscode"))
// Use Gosod to install the template
installer, err := gosod.TemplateDir(sourceDir)
source, err := debme.FS(ides, "ides/vscode")
if err != nil {
return err
}
// Use gosod to install the template
installer := gosod.New(source)
binaryName := filepath.Base(options.TargetDir)
if runtime.GOOS == "windows" {
// yay windows

View File

@@ -11,7 +11,7 @@ type Basic struct {
runtime *wails.Runtime
}
// newBasic creates a new Basic application struct
// NewBasic creates a new Basic application struct
func NewBasic() *Basic {
return &Basic{}
}

View File

@@ -2,6 +2,7 @@
html {
text-align: center;
color: white;
background-color: black;
}
body {

View File

@@ -1,7 +1,7 @@
{
"name": "{{.ProjectName}}",
"outputfilename": "{{.BinaryName}}",
"html": "frontend/index.html",
"html": "frontend/src/index.html",
"author": {
"name": "{{.AuthorName}}",
"email": "{{.AuthorEmail}}"

View File

@@ -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)
}

View File

@@ -1,3 +1,3 @@
package main
var version = "v2.0.0-alpha.64"
var version = "v2.0.0-alpha.65"

View File

@@ -10,8 +10,9 @@ require (
github.com/imdario/mergo v0.3.11
github.com/jackmordaunt/icns v1.0.0
github.com/leaanthony/clir v1.0.4
github.com/leaanthony/debme v1.1.2
github.com/leaanthony/go-ansi-parser v1.0.1
github.com/leaanthony/gosod v0.0.4
github.com/leaanthony/gosod v1.0.1
github.com/leaanthony/slicer v1.5.0
github.com/matryer/is v1.4.0
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // indirect

View File

@@ -41,10 +41,13 @@ github.com/klauspost/compress v1.10.3 h1:OP96hzwJVBIHYU52pVTI6CczrxPvrGfgqF9N5eT
github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
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.1.1/go.mod h1:3V+sCm5tYAgQymvSOfYQ5Xx2JCr+OXiD9Jkw3otUjiA=
github.com/leaanthony/debme v1.1.2 h1:dGeQuj0+xPIlDQzGIjmAU52+yRg85u5pWaaqrdLBjD0=
github.com/leaanthony/debme v1.1.2/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/gosod v0.0.4 h1:v4hepo4IyL8E8c9qzDsvYcA0KGh7Npf8As74K5ibQpI=
github.com/leaanthony/gosod v0.0.4/go.mod h1:nGMCb1PJfXwBDbOAike78jEYlpqge+xUKFf0iBKjKxU=
github.com/leaanthony/gosod v1.0.1 h1:F+4c3DmEBfigi7oAswCV2RpQ+k4DcNbhuCZUGdBHacQ=
github.com/leaanthony/gosod v1.0.1/go.mod h1:W8RyeSFBXu7RpIxPGEJfW4moSyGGEjlJMLV25wEbAdU=
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/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y=

7
v2/init.go Normal file
View File

@@ -0,0 +1,7 @@
// +build !windows
package wails
func Init() error {
return nil
}

14
v2/init_windows.go Normal file
View File

@@ -0,0 +1,14 @@
package wails
import (
"fmt"
"syscall"
)
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
}

View File

@@ -14,30 +14,6 @@ import (
"github.com/leaanthony/slicer"
)
const _comment = `
const backend = {
main: {
"xbarApp": {
"GetCategories": () => {
window.backend.main.xbarApp.GetCategories.call(arguments);
},
/**
* @param {string} arg1
*/
"InstallPlugin": (arg1) => {
window.backend.main.xbarApp.InstallPlugin.call(arguments);
},
"GetPlugins": () => {
window.backend.main.xbarApp.GetPlugins.call(arguments);
}
}
}
}
export default backend;`
//go:embed assets/package.json
var packageJSON []byte
@@ -100,6 +76,8 @@ const backend = {`)
}
returnType += ">"
returnTypeDetails = " - Go Type: " + methodDetails.Outputs[0].TypeName
} else {
returnType = "Promise<void>"
}
output.WriteString(" * @returns {" + returnType + "} " + returnTypeDetails + "\n")
output.WriteString(" */\n")
@@ -125,13 +103,14 @@ const backend = {`)
export default backend;`)
output.WriteString("\n")
// TODO: Make this configurable in wails.json
dirname, err := fs.RelativeToCwd("frontend/src/backend")
if err != nil {
log.Fatal(err)
}
if !fs.DirExists(dirname) {
err := fs.Mkdir(dirname)
err := fs.MkDirs(dirname)
if err != nil {
log.Fatal(err)
}
@@ -165,6 +144,8 @@ func goTypeToJSDocType(input string) string {
return "number"
case input == "bool":
return "boolean"
case input == "[]byte":
return "string"
case strings.HasPrefix(input, "[]"):
arrayType := goTypeToJSDocType(input[2:])
return "Array.<" + arrayType + ">"

View File

@@ -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.<number>",
},
{
name: "[]bool",
input: "[]bool",
want: "Array.<boolean>",
},
{
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)
}
})
}
}

View File

@@ -26,9 +26,8 @@ func (b BridgeClient) Quit() {
}
func (b BridgeClient) NotifyEvent(message string) {
//b.session.sendMessage("n" + message)
b.session.sendMessage("n" + message)
b.session.log.Info("NotifyEvent: %s", message)
b.session.log.Info("NotifyEvent unsupported in Bridge mode")
}
func (b BridgeClient) CallResult(message string) {

File diff suppressed because one or more lines are too long

View File

@@ -1,5 +1,11 @@
# 3rd Party Licenses
## Webview
Whilst not using the library directly, there is certainly some code that is inspired by or used from the webview library.
Homepage: https://github.com/webview/webview
License: https://github.com/webview/webview/blob/master/LICENSE
## vec
Homepage: https://github.com/rxi/vec
License: https://github.com/rxi/vec/blob/master/LICENSE

View File

@@ -1,3 +1,6 @@
// +build !windows
//
// Created by Lea Anthony on 6/1/21.
//

View File

@@ -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*);

View File

@@ -13,17 +13,17 @@ import (
)
/*
#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 -lwebview -lWebView2Loader -lgdi32 -lole32 -lShlwapi -luser32 -loleaut32
#include <stdlib.h>
#include "ffenestri.h"
*/
import "C"
@@ -65,14 +65,6 @@ func NewApplicationWithConfig(config *options.App, logger *logger.Logger, menuMa
}
}
// NewApplication creates a new Application with the default config
func NewApplication(logger *logger.Logger) *Application {
return &Application{
config: options.Default,
logger: logger.CustomLogger("Ffenestri"),
}
}
func (a *Application) freeMemory() {
for _, mem := range a.memory {
// fmt.Printf("Freeing memory: %+v\n", mem)
@@ -139,9 +131,9 @@ func (a *Application) Run(incomingDispatcher Dispatcher, bindings string, debug
C.SetDebug(app, a.bool2Cint(debug))
// TODO: Move frameless to Linux options
// if a.config.Frameless {
// C.DisableFrame(a.app)
// }
if a.config.Frameless {
C.DisableFrame(a.app)
}
if a.config.RGBA != 0 {
r, g, b, alpha := intToColour(a.config.RGBA)
@@ -173,7 +165,7 @@ func (a *Application) Run(incomingDispatcher Dispatcher, bindings string, debug
// 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
}

View File

@@ -1,6 +1,10 @@
#ifndef __FFENESTRI_H__
#define __FFENESTRI_H__
#ifdef __cplusplus
extern "C" {
#endif
#include <stdio.h>
struct Application;
@@ -41,5 +45,11 @@ 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 WindowBackgroundIsTranslucent(struct Application*);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -1,13 +1,7 @@
package ffenestri
/*
#cgo linux CFLAGS: -DFFENESTRI_LINUX=1
#cgo linux pkg-config: gtk+-3.0 webkit2gtk-4.0
#include <stdlib.h>
#include "ffenestri.h"
*/
import "C"

View File

@@ -1,78 +0,0 @@
typedef struct {
} Application;
struct Application *NewApplication(const char *title, int width, int height, int resizable, int devtools, int fullscreen, int startHidden, int logLevel, int hideWindowOnClose) {
}
void SetMinWindowSize(struct Application* app, int minWidth, int minHeight) {
}
void SetMaxWindowSize(struct Application* app, int maxWidth, int maxHeight) {
}
void Run(struct Application* app, int argc, char **argv) {
}
void DestroyApplication(struct Application* app) {
}
void SetDebug(struct Application* app, int flag) {
}
void SetBindings(struct Application* app, const char *bindings) {
}
void ExecJS(struct Application* app, const char *script) {
}
void Hide(struct Application* app) {
}
void Show(struct Application* app) {
}
void Center(struct Application* app) {
}
void Maximise(struct Application* app) {
}
void Unmaximise(struct Application* app) {
}
void ToggleMaximise(struct Application* app) {
}
void Minimise(struct Application* app) {
}
void Unminimise(struct Application* app) {
}
void ToggleMinimise(struct Application* app) {
}
void SetColour(struct Application* app, int red, int green, int blue, int alpha) {
}
void SetSize(struct Application* app, int width, int height) {
}
void SetPosition(struct Application* app, int x, int y) {
}
void Quit(struct Application* app) {
}
void SetTitle(struct Application* app, const char *title) {
}
void Fullscreen(struct Application* app) {
}
void UnFullscreen(struct Application* app) {
}
void ToggleFullscreen(struct Application* app) {
}
void DisableFrame(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) {
}
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) {
}

View File

@@ -0,0 +1,620 @@
// Some code may be inspired by or directly used from Webview (c) zserge.
// License included in README.md
#include "ffenestri_windows.h"
#include "wv2ComHandler_windows.h"
#include <functional>
#include <atomic>
#include <Shlwapi.h>
#include <locale>
#include <codecvt>
#include "windows/WebView2.h"
#include "effectstructs_windows.h"
#include <Shlobj.h>
int debug = 0;
DWORD mainThread;
// --- 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));
}
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;
}
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->windowBackgroundIsTranslucent = 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;
return result;
}
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");
}
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_DESTROY: {
DestroyApplication(app);
break;
}
case WM_SIZE: {
if( app->webviewController != nullptr) {
RECT bounds;
GetClientRect(app->window, &bounds);
app->webviewController->put_Bounds(bounds);
}
break;
}
case WM_GETMINMAXINFO: {
// Exit early if this is called before the window is created.
if ( app == NULL ) {
return 0;
}
// get pixel density
HDC hDC = GetDC(NULL);
double DPIScaleX = GetDeviceCaps(hDC, 88)/96.0;
double DPIScaleY = GetDeviceCaps(hDC, 90)/96.0;
ReleaseDC(NULL, hDC);
RECT rcClient, rcWind;
POINT ptDiff;
GetClientRect(hwnd, &rcClient);
GetWindowRect(hwnd, &rcWind);
int widthExtra = (rcWind.right - rcWind.left) - rcClient.right;
int heightExtra = (rcWind.bottom - rcWind.top) - rcClient.bottom;
LPMINMAXINFO mmi = (LPMINMAXINFO) lParam;
if (app->minWidth > 0 && app->minHeight > 0) {
mmi->ptMinTrackSize.x = app->minWidth * DPIScaleX + widthExtra;
mmi->ptMinTrackSize.y = app->minHeight * DPIScaleY + heightExtra;
}
if (app->maxWidth > 0 && app->maxHeight > 0) {
mmi->ptMaxSize.x = app->maxWidth * DPIScaleX + widthExtra;
mmi->ptMaxSize.y = app->maxHeight * DPIScaleY + heightExtra;
mmi->ptMaxTrackSize.x = app->maxWidth * DPIScaleX + widthExtra;
mmi->ptMaxTrackSize.y = app->maxHeight * DPIScaleY + heightExtra;
}
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) {
// patch window.external.invoke
std::string initialCode = std::string("window.external={invoke:s=>window.chrome.webview.postMessage(s)};");
// 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.external.invoke('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;
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<std::codecvt_utf8_utf16<wchar_t>> wideCharConverter;
// auto exeName = wideCharConverter.from_bytes(currentExeName);
//
// PWSTR path;
// HRESULT appDataResult = SHGetFolderPathAndSubDir(app->window, CSIDL_LOCAL_APPDATA, nullptr, SHGFP_TYPE_CURRENT, exeName.c_str(), path);
// if ( appDataResult == false ) {
// path = nullptr;
// }
//
ICoreWebView2Controller *controller;
ICoreWebView2* webview;
HRESULT res = CreateCoreWebView2EnvironmentWithOptions(
nullptr, nullptr, nullptr,
new wv2ComHandler(app, app->window, cb,
[&](ICoreWebView2Controller *webviewController) {
controller = webviewController;
controller->get_CoreWebView2(&webview);
webview->AddRef();
flag.clear();
}));
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);
// Callback hack
app->webview->AddScriptToExecuteOnDocumentCreated(L"window.chrome.webview.postMessage('I');", nullptr);
// Load the HTML
LPCWSTR html = (LPCWSTR) cstrToLPWSTR((char*)assets[0]);
app->webview->Navigate(html);
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) {
WNDCLASSEX wc;
HINSTANCE hInstance = GetModuleHandle(NULL);
ZeroMemory(&wc, sizeof(WNDCLASSEX));
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.hInstance = hInstance;
wc.lpszClassName = (LPCWSTR)"ffenestri";
wc.lpfnWndProc = WndProc;
// TODO: Menu
// wc.lpszMenuName = nullptr;
// Process window resizable
DWORD windowStyle = WS_OVERLAPPEDWINDOW;
if (app->resizable == 0) {
windowStyle &= ~WS_MAXIMIZEBOX;
windowStyle &= ~WS_THICKFRAME;
}
if ( app->frame == 0 ) {
windowStyle = WS_POPUP;
}
RegisterClassEx(&wc);
app->window = CreateWindow((LPCWSTR)"ffenestri", (LPCWSTR)"", windowStyle, CW_USEDEFAULT,
CW_USEDEFAULT, app->width, app->height, NULL, NULL,
hInstance, NULL);
// Private setTitle as we're on the main thread
setTitle(app, app->title);
// Store application pointer in window handle
SetWindowLongPtr(app->window, GWLP_USERDATA, (LONG_PTR)app);
// Process whether window should show by default
int startVisibility = SW_SHOWNORMAL;
if ( app->startHidden == 1 ) {
startVisibility = SW_HIDE;
}
// TODO: Make configurable
// COREWEBVIEW2_COLOR wvColor;
// wvColor.A = 255;
// std::weak_ptr<ICoreWebView2Controller2> controller2 = app->webviewController->query<ICoreWebView2Controller2>();
// controller2->put_DefaultBackgroundColor(wvColor);
if( app->windowBackgroundIsTranslucent ) {
enableTranslucentBackground(app);
}
// private center() as we are on main thread
center(app);
ShowWindow(app->window, startVisibility);
UpdateWindow(app->window);
SetFocus(app->window);
// Add webview2
initWebView2(app, 1, 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 DestroyApplication(struct Application* app) {
PostQuitMessage(0);
}
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 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) {
// TBD
}
void SetSize(struct Application* app, int width, int height) {
// TBD
}
void setPosition(struct Application* app, int x, int y) {
// TBD
}
void SetPosition(struct Application* app, int x, int y) {
// ON_MAIN_THREAD(
// setPosition(app, x, y);
// );
}
void Quit(struct Application* app) {
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) {
}
void UnFullscreen(struct Application* app) {
}
void ToggleFullscreen(struct Application* 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 WindowBackgroundIsTranslucent(struct Application *app) {
app->windowBackgroundIsTranslucent = 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) {
}

View File

@@ -1,14 +1,63 @@
package ffenestri
import "C"
/*
#cgo windows CXXFLAGS: -std=c++11
#cgo windows,amd64 LDFLAGS: -L./windows/x64 -lwebview -lWebView2Loader -lgdi32 -lole32 -lShlwapi -luser32 -loleaut32
#include "ffenestri.h"
#include "ffenestri_windows.h"
*/
import "C"
func (a *Application) processPlatformSettings() error {
config := a.config.Windows
// Check if the webview should be transparent
if config.WebviewIsTransparent {
C.WebviewIsTransparent(a.app)
}
if config.WindowBackgroundIsTranslucent {
C.WindowBackgroundIsTranslucent(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
}

View File

@@ -1,5 +1,75 @@
#ifndef _FFENESTRI_WINDOWS_
#define _FFENESTRI_WINDOWS_
#ifndef _FFENESTRI_WINDOWS_H
#define _FFENESTRI_WINDOWS_H
#define WIN32_LEAN_AND_MEAN
#define UNICODE 1
#include "ffenestri.h"
#include <windows.h>
#include <wingdi.h>
#include <functional>
#include <codecvt>
#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 windowBackgroundIsTranslucent;
COREWEBVIEW2_COLOR backgroundColour;
// placeholders
char* bindings;
char* initialCode;
};
#define ON_MAIN_THREAD(code) dispatch( [=]{ code; } )
typedef std::function<void()> dispatchFunction;
typedef std::function<void(const std::string)> messageCallback;
typedef std::function<void(ICoreWebView2Controller *)> comHandlerCallback;
void center(struct Application*);
void setTitle(struct Application* app, const char *title);
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);
// Callback
extern "C" {
void messageFromWindowCallback(const char *);
}
#endif

View File

@@ -1,3 +1,5 @@
// +build !windows
/*
Copyright (C) 2011 Joseph A. Adams (joeyadams3.14159@gmail.com)
All rights reserved.

File diff suppressed because one or more lines are too long

View File

@@ -1,4 +1,6 @@
/**
// +build !windows
/**
* Copyright (c) 2014 rxi
*
* This library is free software; you can redistribute it and/or modify it

View File

@@ -1,4 +1,4 @@
/**
/**
* Copyright (c) 2014 rxi
*
* This library is free software; you can redistribute it and/or modify it

View File

@@ -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 <rpcndr.h> version is high enough to compile this file*/
#ifndef __REQUIRED_RPCNDR_H_VERSION__
#define __REQUIRED_RPCNDR_H_VERSION__ 500
#endif
/* verify that the <rpcsal.h> 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 <rpcndr.h>
#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

View File

@@ -0,0 +1 @@
These files were generated using the scripts in the [webview](https://github.com/webview/webview) project and compressed using UPX.

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,7 @@
cmake_minimum_required(VERSION 3.19)
project(test C)
set(CMAKE_C_STANDARD 99)
set(SOURCES ../../ffenestri_windows.cpp)
add_executable(test ${SOURCES} main.c)

View File

@@ -0,0 +1 @@
g++ main.c ..\..\ffenestri_windows.cpp -lgdi32 -std=c++11

Binary file not shown.

View File

@@ -0,0 +1,11 @@
// +build windows
package x64
import _ "embed"
//go:embed webview.dll
var WebView2 []byte
//go:embed WebView2Loader.dll
var WebView2Loader []byte

View File

@@ -0,0 +1,9 @@
// +build !windows
// This is a stub to define the following even though they don't exist
// on non-Windows systems. Note: This is not the right way to handle this.
package x64
var WebView2 []byte
var WebView2Loader []byte

View File

@@ -0,0 +1,103 @@
#ifndef WV2COMHANDLER_H
#define WV2COMHANDLER_H
#include "ffenestri_windows.h"
#include "windows/WebView2.h"
#include <locale>
#include <codecvt>
class wv2ComHandler
: public ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler,
public ICoreWebView2CreateCoreWebView2ControllerCompletedHandler,
public ICoreWebView2WebMessageReceivedEventHandler,
public ICoreWebView2PermissionRequestedEventHandler
{
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);
webview->add_WebMessageReceived(this, &token);
webview->add_PermissionRequested(this, &token);
cb(controller);
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;
}
switch(m[0]) {
// Standard message for backend
case 'S':
printf("--> Message to backend: %s\n", &m[1]);
messageFromWindowCallback(&m[1]);
break;
// DOM Initialised
case 'I':
loadAssets(app);
break;
default:
printf("----> Unknown message type: %c\n", m[0]);
}
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

View File

@@ -201,10 +201,6 @@ func GetSubdirectories(rootDir string) (*slicer.StringSlicer, error) {
func DirIsEmpty(dir string) (bool, error) {
if !DirExists(dir) {
return false, fmt.Errorf("DirIsEmpty called with a non-existant directory: %s", dir)
}
// CREDIT: https://stackoverflow.com/a/30708914/8325411
f, err := os.Open(dir)
if err != nil {

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -3,12 +3,12 @@
"browser": true,
"es6": true,
"amd": true,
"node": true,
"node": true
},
"extends": "eslint:recommended",
"parserOptions": {
"ecmaVersion": 2016,
"sourceType": "module",
"ecmaVersion": 2020,
"sourceType": "module"
},
"rules": {
"linebreak-style": 0,

View File

@@ -0,0 +1,72 @@
/*
_ __ _ __
| | / /___ _(_) /____
| | /| / / __ `/ / / ___/
| |/ |/ / /_/ / / (__ )
|__/|__/\__,_/_/_/____/
The lightweight framework for web-like apps
(c) Lea Anthony 2019-present
*/
/* jshint esversion: 9 */
/**
* Initialises platform specific code
*/
// import * as common from './common';
const common = require('./common');
export const System = {
...common,
Platform: () => 'windows',
};
export function SendMessage(message) {
window.chrome.webview.postMessage('S'+message);
}
export function RaiseError(message) {
window.chrome.webview.postMessage('E'+message);
}
export function Init() {
// Setup drag handler
// Based on code from: https://github.com/patr0nus/DeskGap
window.addEventListener('mousedown', function (e) {
let currentElement = e.target;
while (currentElement != null) {
if (currentElement.hasAttribute('data-wails-no-drag')) {
break;
} else if (currentElement.hasAttribute('data-wails-drag')) {
window.chrome.webview.postMessage('wails-drag');
break;
}
currentElement = currentElement.parentElement;
}
});
// Setup context menu hook
window.addEventListener('contextmenu', function (e) {
let currentElement = e.target;
let contextMenuId;
while (currentElement != null) {
contextMenuId = currentElement.dataset['wails-context-menu-id'];
if (contextMenuId != null) {
break;
}
currentElement = currentElement.parentElement;
}
if (contextMenuId != null || window.disableWailsDefaultContextMenu) {
e.preventDefault();
}
if( contextMenuId != null ) {
let contextData = currentElement.dataset['wails-context-menu-data'];
let message = {
id: contextMenuId,
data: contextData || '',
};
window.chrome.webview.postMessage('C'+JSON.stringify(message));
}
});
}

View File

@@ -4,8 +4,8 @@
"description": "The Javascript Wails Runtime",
"main": "index.js",
"scripts": {
"build:desktop": "./node_modules/.bin/eslint core/ && ./node_modules/.bin/webpack --env desktop --colors",
"build:server": "./node_modules/.bin/eslint core/ && ./node_modules/.bin/webpack --env server --colors",
"build:desktop": "npx eslint core/ && npx webpack --env desktop --colors",
"build:server": "npx eslint core/ && npx webpack --env server --colors",
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {

View File

@@ -1647,10 +1647,10 @@
}
// });
break;
// // Notifications
// case 'n':
// addScript(message.data.slice(1), true);
// break;
// Notifications
case 'n':
window.wails._.Notify(message.data.slice(1));
break;
// // Binding
// case 'b':
// const binding = message.data.slice(1);

View File

@@ -1,6 +1,6 @@
{
"name": "@wails/runtime",
"version": "1.3.12",
"version": "1.3.13",
"description": "Wails V2 Javascript runtime library",
"main": "main.js",
"types": "runtime.d.ts",

View File

@@ -1,8 +1,616 @@
{
"name": "bridge",
"version": "1.0.0",
"lockfileVersion": 1,
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "bridge",
"version": "1.0.0",
"license": "ISC",
"devDependencies": {
"@rollup/plugin-commonjs": "^17.1.0",
"@rollup/plugin-node-resolve": "^11.1.1",
"rollup": "^2.38.5",
"rollup-plugin-svelte": "^7.1.0",
"rollup-plugin-terser": "^7.0.2",
"svelte": "^3.32.2"
}
},
"node_modules/@babel/code-frame": {
"version": "7.12.13",
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.13.tgz",
"integrity": "sha512-HV1Cm0Q3ZrpCR93tkWOYiuYIgLxZXZFVG2VgK+MBWjUqZTundupbfx2aXarXuw5Ko5aMcjtJgbSs4vUGBS5v6g==",
"dev": true,
"dependencies": {
"@babel/highlight": "^7.12.13"
}
},
"node_modules/@babel/helper-validator-identifier": {
"version": "7.12.11",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz",
"integrity": "sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw==",
"dev": true
},
"node_modules/@babel/highlight": {
"version": "7.12.13",
"resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.12.13.tgz",
"integrity": "sha512-kocDQvIbgMKlWxXe9fof3TQ+gkIPOUSEYhJjqUjvKMez3krV7vbzYCDq39Oj11UAVK7JqPVGQPlgE85dPNlQww==",
"dev": true,
"dependencies": {
"@babel/helper-validator-identifier": "^7.12.11",
"chalk": "^2.0.0",
"js-tokens": "^4.0.0"
}
},
"node_modules/@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,
"dependencies": {
"@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"
},
"engines": {
"node": ">= 8.0.0"
}
},
"node_modules/@rollup/plugin-commonjs/node_modules/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
},
"node_modules/@rollup/plugin-node-resolve": {
"version": "11.1.1",
"resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-11.1.1.tgz",
"integrity": "sha512-zlBXR4eRS+2m79TsUZWhsd0slrHUYdRx4JF+aVQm+MI0wsKdlpC2vlDVjmlGvtZY1vsefOT9w3JxvmWSBei+Lg==",
"dev": true,
"dependencies": {
"@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"
},
"engines": {
"node": ">= 10.0.0"
}
},
"node_modules/@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,
"dependencies": {
"@types/estree": "0.0.39",
"estree-walker": "^1.0.1",
"picomatch": "^2.2.2"
},
"engines": {
"node": ">= 8.0.0"
}
},
"node_modules/@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
},
"node_modules/@types/node": {
"version": "14.14.25",
"resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.25.tgz",
"integrity": "sha512-EPpXLOVqDvisVxtlbvzfyqSsFeQxltFbluZNRndIb8tr9KiBnYNLzrc1N3pyKUCww2RNrfHDViqDWWE1LCJQtQ==",
"dev": true
},
"node_modules/@types/resolve": {
"version": "1.17.1",
"resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz",
"integrity": "sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==",
"dev": true,
"dependencies": {
"@types/node": "*"
}
},
"node_modules/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,
"dependencies": {
"color-convert": "^1.9.0"
},
"engines": {
"node": ">=4"
}
},
"node_modules/balanced-match": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
"dev": true
},
"node_modules/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,
"dependencies": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
}
},
"node_modules/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
},
"node_modules/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,
"engines": {
"node": ">=6"
}
},
"node_modules/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,
"dependencies": {
"ansi-styles": "^3.2.1",
"escape-string-regexp": "^1.0.5",
"supports-color": "^5.3.0"
},
"engines": {
"node": ">=4"
}
},
"node_modules/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,
"dependencies": {
"color-name": "1.1.3"
}
},
"node_modules/color-name": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
"dev": true
},
"node_modules/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
},
"node_modules/commondir": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz",
"integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=",
"dev": true
},
"node_modules/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
},
"node_modules/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,
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/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,
"engines": {
"node": ">=0.8.0"
}
},
"node_modules/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
},
"node_modules/fs.realpath": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
"dev": true
},
"node_modules/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,
"os": [
"darwin"
],
"engines": {
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
}
},
"node_modules/function-bind": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
"dev": true
},
"node_modules/glob": {
"version": "7.1.6",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
"integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
"dev": true,
"dependencies": {
"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"
},
"engines": {
"node": "*"
}
},
"node_modules/has": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
"integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
"dev": true,
"dependencies": {
"function-bind": "^1.1.1"
},
"engines": {
"node": ">= 0.4.0"
}
},
"node_modules/has-flag": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
"integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
"dev": true,
"engines": {
"node": ">=4"
}
},
"node_modules/inflight": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
"integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
"dev": true,
"dependencies": {
"once": "^1.3.0",
"wrappy": "1"
}
},
"node_modules/inherits": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
"dev": true
},
"node_modules/is-core-module": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.2.0.tgz",
"integrity": "sha512-XRAfAdyyY5F5cOXn7hYQDqh2Xmii+DEfIcQGxK/uNwMHhIkPWO0g8msXcbzLe+MpGoR951MlqM/2iIlU4vKDdQ==",
"dev": true,
"dependencies": {
"has": "^1.0.3"
}
},
"node_modules/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
},
"node_modules/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,
"dependencies": {
"@types/estree": "*"
}
},
"node_modules/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,
"dependencies": {
"@types/node": "*",
"merge-stream": "^2.0.0",
"supports-color": "^7.0.0"
},
"engines": {
"node": ">= 10.13.0"
}
},
"node_modules/jest-worker/node_modules/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,
"engines": {
"node": ">=8"
}
},
"node_modules/jest-worker/node_modules/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,
"dependencies": {
"has-flag": "^4.0.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/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
},
"node_modules/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,
"dependencies": {
"sourcemap-codec": "^1.4.4"
}
},
"node_modules/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
},
"node_modules/minimatch": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
"dev": true,
"dependencies": {
"brace-expansion": "^1.1.7"
},
"engines": {
"node": "*"
}
},
"node_modules/once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
"dev": true,
"dependencies": {
"wrappy": "1"
}
},
"node_modules/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,
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/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==",
"dev": true
},
"node_modules/picomatch": {
"version": "2.2.2",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz",
"integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==",
"dev": true,
"engines": {
"node": ">=8.6"
}
},
"node_modules/randombytes": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
"integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==",
"dev": true,
"dependencies": {
"safe-buffer": "^5.1.0"
}
},
"node_modules/require-relative": {
"version": "0.8.7",
"resolved": "https://registry.npmjs.org/require-relative/-/require-relative-0.8.7.tgz",
"integrity": "sha1-eZlTn8ngR6N5KPoZb44VY9q9Nt4=",
"dev": true
},
"node_modules/resolve": {
"version": "1.19.0",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.19.0.tgz",
"integrity": "sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==",
"dev": true,
"dependencies": {
"is-core-module": "^2.1.0",
"path-parse": "^1.0.6"
}
},
"node_modules/rollup": {
"version": "2.38.5",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-2.38.5.tgz",
"integrity": "sha512-VoWt8DysFGDVRGWuHTqZzT02J0ASgjVq/hPs9QcBOGMd7B+jfTr/iqMVEyOi901rE3xq+Deq66GzIT1yt7sGwQ==",
"dev": true,
"bin": {
"rollup": "dist/bin/rollup"
},
"engines": {
"node": ">=10.0.0"
},
"optionalDependencies": {
"fsevents": "~2.3.1"
}
},
"node_modules/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,
"dependencies": {
"require-relative": "^0.8.7",
"rollup-pluginutils": "^2.8.2"
},
"engines": {
"node": ">=10"
}
},
"node_modules/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,
"dependencies": {
"@babel/code-frame": "^7.10.4",
"jest-worker": "^26.2.1",
"serialize-javascript": "^4.0.0",
"terser": "^5.0.0"
}
},
"node_modules/rollup-pluginutils": {
"version": "2.8.2",
"resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz",
"integrity": "sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==",
"dev": true,
"dependencies": {
"estree-walker": "^0.6.1"
}
},
"node_modules/rollup-pluginutils/node_modules/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
},
"node_modules/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
},
"node_modules/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,
"dependencies": {
"randombytes": "^2.1.0"
}
},
"node_modules/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,
"engines": {
"node": ">= 8"
}
},
"node_modules/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,
"dependencies": {
"buffer-from": "^1.0.0",
"source-map": "^0.6.0"
}
},
"node_modules/source-map-support/node_modules/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,
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/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
},
"node_modules/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,
"dependencies": {
"has-flag": "^3.0.0"
},
"engines": {
"node": ">=4"
}
},
"node_modules/svelte": {
"version": "3.32.2",
"resolved": "https://registry.npmjs.org/svelte/-/svelte-3.32.2.tgz",
"integrity": "sha512-Zxh1MQQl/+vnToKbU1Per+PoMN8Jb2MeKJcGxiOsCGR677hXw7jkMfbnNXq33+dxIzV/HfA4xtoSPJrqeB0VUg==",
"dev": true,
"engines": {
"node": ">= 8"
}
},
"node_modules/terser": {
"version": "5.5.1",
"resolved": "https://registry.npmjs.org/terser/-/terser-5.5.1.tgz",
"integrity": "sha512-6VGWZNVP2KTUcltUQJ25TtNjx/XgdDsBDKGt8nN0MpydU36LmbPPcMBd2kmtZNNGVVDLg44k7GKeHHj+4zPIBQ==",
"dev": true,
"dependencies": {
"commander": "^2.20.0",
"source-map": "~0.7.2",
"source-map-support": "~0.5.19"
},
"bin": {
"terser": "bin/terser"
},
"engines": {
"node": ">=10"
}
},
"node_modules/wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
"dev": true
}
},
"dependencies": {
"@babel/code-frame": {
"version": "7.12.13",

View File

@@ -123,10 +123,10 @@ function handleMessage(message) {
}
// });
break;
// // Notifications
// case 'n':
// addScript(message.data.slice(1), true);
// break;
// Notifications
case 'n':
window.wails._.Notify(message.data.slice(1));
break;
// // Binding
// case 'b':
// const binding = message.data.slice(1);

View File

@@ -16,7 +16,7 @@ func main() {
sourceDir := fs.RelativePath("../../../internal/runtime/js")
platforms := []string{"darwin"}
platforms := []string{"darwin", "windows"}
for _, platform := range platforms {
println("Building JS Runtime for " + platform)

View File

@@ -1,20 +0,0 @@
package templates
import (
"fmt"
"testing"
"github.com/matryer/is"
)
func TestList(t *testing.T) {
is := is.New(t)
templates, err := List()
is.Equal(err, nil)
println("Found these templates:")
for _, template := range templates {
fmt.Printf("%+v\n", template)
}
}

View File

@@ -3,6 +3,7 @@ package build
import (
"bytes"
"fmt"
"github.com/wailsapp/wails/v2/internal/ffenestri/windows/x64"
"io/ioutil"
"os"
"os/exec"
@@ -264,6 +265,14 @@ func (b *BaseBuilder) CompileProject(options *Options) error {
v += "-I" + buildBaseDir
return v
})
// Use upsertEnv so we don't overwrite user's CGO_CXXFLAGS
cmd.Env = upsertEnv(cmd.Env, "CGO_CXXFLAGS", func(v string) string {
if v != "" {
v += " "
}
v += "-I" + buildBaseDir
return v
})
cmd.Env = upsertEnv(cmd.Env, "GOOS", func(v string) string {
return options.Platform
@@ -294,10 +303,25 @@ func (b *BaseBuilder) CompileProject(options *Options) error {
return fmt.Errorf("%s\n%s", err, string(stde.Bytes()))
}
println("Done.")
// If we are targeting windows, dump the DLLs
if options.Platform == "windows" {
err := os.WriteFile(filepath.Join(appDir, "webview2.dll"), x64.WebView2, 0755)
if err != nil {
return err
}
err = os.WriteFile(filepath.Join(appDir, "WebView2Loader.dll"), x64.WebView2Loader, 0755)
if err != nil {
return err
}
}
if !options.Compress {
return nil
}
println("Compressing application: ")
// Do we have upx installed?
if !shell.CommandExists("upx") {
println("Warning: Cannot compress binary: upx not found")
@@ -305,10 +329,10 @@ func (b *BaseBuilder) CompileProject(options *Options) error {
}
if verbose {
println(" Compressing with:", "upx", "--best", "--no-color", "--no-progress", options.CompiledBinary)
println("upx", "--best", "--no-color", "--no-progress", options.CompiledBinary)
}
output, err := exec.Command(options.BuildDirectory, "upx", "--best", "--no-color", "--no-progress", options.CompiledBinary).Output()
output, err := exec.Command("upx", "--best", "--no-color", "--no-progress", options.CompiledBinary).Output()
if err != nil {
return errors.Wrap(err, "Error during compression:")
}
@@ -414,7 +438,6 @@ func (b *BaseBuilder) NpmRunWithEnvironment(projectDir, buildTarget string, verb
// BuildFrontend executes the `npm build` command for the frontend directory
func (b *BaseBuilder) BuildFrontend(outputLogger *clilogger.CLILogger) error {
// TODO: Fix this up from the CLI
verbose := b.options.Verbosity == VERBOSE
frontendDir := filepath.Join(b.projectData.Path, "frontend")

View File

@@ -0,0 +1,181 @@
// +build windows
package build
// We will compile all tray icons found at <projectdir>/assets/trayicons/*.png into the application
func (d *DesktopBuilder) processTrayIcons(assetDir string, options *Options) error {
//
// var err error
//
// // Get all the tray icon filenames
// trayIconDirectory := filepath.Join(options.ProjectData.AssetsDir, "tray")
//
// // If the directory doesn't exist, create it
// if !fs.DirExists(trayIconDirectory) {
// err = fs.MkDirs(trayIconDirectory)
// if err != nil {
// return err
// }
// }
//
// var trayIconFilenames []string
// trayIconFilenames, err = filepath.Glob(trayIconDirectory + "/*.png")
// if err != nil {
// log.Fatal(err)
// return err
// }
//
// // Setup target
// targetFilename := "trayicons"
// targetFile := filepath.Join(assetDir, targetFilename+".h")
// d.addFileToDelete(targetFile)
//
// var dataBytes []byte
//
// // Use a strings builder
// var cdata strings.Builder
//
// // Write header
// header := `// trayicons.h
//// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Ă‚ MODIWL.
//// This file was auto-generated. DO NOT MODIFY.
//
//`
// cdata.WriteString(header)
//
// var variableList slicer.StringSlicer
//
// // Loop over icons
// for count, filename := range trayIconFilenames {
//
// // Load the tray icon
// dataBytes, err = ioutil.ReadFile(filename)
// if err != nil {
// return err
// }
//
// iconname := strings.TrimSuffix(filepath.Base(filename), ".png")
// trayIconName := fmt.Sprintf("trayIcon%dName", count)
// variableList.Add(trayIconName)
// cdata.WriteString(fmt.Sprintf("const unsigned char %s[] = { %s0x00 };\n", trayIconName, d.convertToHexLiteral([]byte(iconname))))
//
// trayIconLength := fmt.Sprintf("trayIcon%dLength", count)
// variableList.Add(trayIconLength)
// lengthAsString := strconv.Itoa(len(dataBytes))
// cdata.WriteString(fmt.Sprintf("const unsigned char %s[] = { %s0x00 };\n", trayIconLength, d.convertToHexLiteral([]byte(lengthAsString))))
//
// trayIconData := fmt.Sprintf("trayIcon%dData", count)
// variableList.Add(trayIconData)
// cdata.WriteString(fmt.Sprintf("const unsigned char %s[] = { ", trayIconData))
//
// // Convert each byte to hex
// for _, b := range dataBytes {
// cdata.WriteString(fmt.Sprintf("0x%x, ", b))
// }
//
// cdata.WriteString("0x00 };\n")
// }
//
// // Write out main trayIcons data
// cdata.WriteString("const unsigned char *trayIcons[] = { ")
// cdata.WriteString(variableList.Join(", "))
// if len(trayIconFilenames) > 0 {
// cdata.WriteString(", ")
// }
// cdata.WriteString("0x00 };\n")
//
// err = ioutil.WriteFile(targetFile, []byte(cdata.String()), 0600)
// if err != nil {
// return err
// }
return nil
}
// We will compile all dialog icons found at <projectdir>/icons/dialog/*.png into the application
func (d *DesktopBuilder) processDialogIcons(assetDir string, options *Options) error {
// var err error
//
// // Get all the dialog icon filenames
// dialogIconDirectory := filepath.Join(options.ProjectData.AssetsDir, "dialog")
// var dialogIconFilenames []string
//
// // If the directory does not exist, create it
// if !fs.DirExists(dialogIconDirectory) {
// err = fs.MkDirs(dialogIconDirectory)
// if err != nil {
// return err
// }
// }
//
// dialogIconFilenames, err = filepath.Glob(dialogIconDirectory + "/*.png")
// if err != nil {
// log.Fatal(err)
// return err
// }
//
// // Setup target
// targetFilename := "userdialogicons"
// targetFile := filepath.Join(assetDir, targetFilename+".h")
// d.addFileToDelete(targetFile)
//
// var dataBytes []byte
//
// // Use a strings builder
// var cdata strings.Builder
//
// // Write header
// header := `// userdialogicons.h
//// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Ă‚ MODIWL.
//// This file was auto-generated. DO NOT MODIFY.
//
//`
// cdata.WriteString(header)
//
// var variableList slicer.StringSlicer
//
// // Loop over icons
// for count, filename := range dialogIconFilenames {
//
// // Load the tray icon
// dataBytes, err = ioutil.ReadFile(filename)
// if err != nil {
// return err
// }
//
// iconname := strings.TrimSuffix(filepath.Base(filename), ".png")
// dialogIconName := fmt.Sprintf("userDialogIcon%dName", count)
// variableList.Add(dialogIconName)
// cdata.WriteString(fmt.Sprintf("const unsigned char %s[] = { %s0x00 };\n", dialogIconName, d.convertToHexLiteral([]byte(iconname))))
//
// dialogIconLength := fmt.Sprintf("userDialogIcon%dLength", count)
// variableList.Add(dialogIconLength)
// lengthAsString := strconv.Itoa(len(dataBytes))
// cdata.WriteString(fmt.Sprintf("const unsigned char %s[] = { %s0x00 };\n", dialogIconLength, d.convertToHexLiteral([]byte(lengthAsString))))
//
// dialogIconData := fmt.Sprintf("userDialogIcon%dData", count)
// variableList.Add(dialogIconData)
// cdata.WriteString(fmt.Sprintf("const unsigned char %s[] = { ", dialogIconData))
//
// // Convert each byte to hex
// for _, b := range dataBytes {
// cdata.WriteString(fmt.Sprintf("0x%x, ", b))
// }
//
// cdata.WriteString("0x00 };\n")
// }
//
// // Write out main dialogIcons data
// cdata.WriteString("const unsigned char *userDialogIcons[] = { ")
// cdata.WriteString(variableList.Join(", "))
// if len(dialogIconFilenames) > 0 {
// cdata.WriteString(", ")
// }
// cdata.WriteString("0x00 };\n")
//
// err = ioutil.WriteFile(targetFile, []byte(cdata.String()), 0600)
// if err != nil {
// return err
// }
return nil
}

View File

@@ -1,6 +1,7 @@
package options
import (
"github.com/wailsapp/wails/v2/pkg/options/windows"
"log"
"runtime"
@@ -19,6 +20,7 @@ type App struct {
Height int
DisableResize bool
Fullscreen bool
Frameless bool
MinWidth int
MinHeight int
MaxWidth int
@@ -30,6 +32,7 @@ type App struct {
ContextMenus []*menu.ContextMenu
TrayMenus []*menu.TrayMenu
Menu *menu.Menu
Windows *windows.Options
Mac *mac.Options
Logger logger.Logger `json:"-"`
LogLevel logger.LogLevel
@@ -45,6 +48,31 @@ func MergeDefaults(appoptions *App) {
log.Fatal(err)
}
// Ensure max and min are valid
if appoptions.MinWidth > 0 && appoptions.MaxWidth > 0 {
if appoptions.MinWidth > appoptions.MaxWidth {
appoptions.MinWidth = appoptions.MaxWidth
}
}
if appoptions.MinHeight > 0 && appoptions.MaxHeight > 0 {
if appoptions.MinHeight > appoptions.MaxHeight {
appoptions.MinHeight = appoptions.MaxHeight
}
}
// Ensure width and height are limited if max/min is set
if appoptions.Width < appoptions.MinWidth {
appoptions.Width = appoptions.MinWidth
}
if appoptions.Width > appoptions.MaxWidth {
appoptions.Width = appoptions.MaxWidth
}
if appoptions.Height < appoptions.MinHeight {
appoptions.Height = appoptions.MinHeight
}
if appoptions.Height > appoptions.MaxHeight {
appoptions.Height = appoptions.MaxHeight
}
}
func GetTrayMenus(appoptions *App) []*menu.TrayMenu {

View File

@@ -0,0 +1,7 @@
package windows
// Options are options specific to Mac
type Options struct {
WebviewIsTransparent bool
WindowBackgroundIsTranslucent bool
}

View File

@@ -16,10 +16,17 @@ type Store = runtime.Store
// Run creates an application based on the given config and executes it
func Run(options *options.App) error {
app, err := app.CreateApp(options)
// Call an Init method manually
err := Init()
if err != nil {
return err
}
return app.Run()
mainapp, err := app.CreateApp(options)
if err != nil {
return err
}
return mainapp.Run()
}