mirror of
https://github.com/wavetermdev/wails.git
synced 2026-04-22 15:26:15 -07:00
Compare commits
33 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| c24aef8ea1 | |||
| 91934d1f8e | |||
| 2f7293e25c | |||
| 18c76602b5 | |||
| 93491eb2eb | |||
| 2ded86c369 | |||
| f059c35d9e | |||
| 6e8d65e3aa | |||
| a750d2d507 | |||
| 331e0268a3 | |||
| e6424dc8ab | |||
| f923a431f7 | |||
| 00db626942 | |||
| eb0f22b4ee | |||
| e068e0f2f5 | |||
| 771594519f | |||
| ec44ca58f1 | |||
| cb574148eb | |||
| 771efa527f | |||
| 28e31c46c6 | |||
| c2fa4b6103 | |||
| 99ca6d5e77 | |||
| 876b845762 | |||
| e4122ce4d2 | |||
| 7bc51725c0 | |||
| 3d02a314b9 | |||
| 30a4f47cba | |||
| 668da3a827 | |||
| 322aad166b | |||
| 3decd70319 | |||
| 24857ec04b | |||
| a016f39e97 | |||
| 8699bf7521 |
@@ -2,7 +2,6 @@ package build
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/wailsapp/wails/v2/internal/colour"
|
||||
"io"
|
||||
"os"
|
||||
"os/exec"
|
||||
@@ -12,11 +11,13 @@ import (
|
||||
"text/tabwriter"
|
||||
"time"
|
||||
|
||||
"github.com/wailsapp/wails/v2/internal/colour"
|
||||
"github.com/wailsapp/wails/v2/internal/project"
|
||||
"github.com/wailsapp/wails/v2/internal/system"
|
||||
|
||||
"github.com/wailsapp/wails/v2/cmd/wails/internal"
|
||||
"github.com/wailsapp/wails/v2/internal/gomod"
|
||||
|
||||
"github.com/wailsapp/wails/v2/internal/system"
|
||||
|
||||
"github.com/leaanthony/clir"
|
||||
"github.com/leaanthony/slicer"
|
||||
"github.com/wailsapp/wails/v2/pkg/clilogger"
|
||||
@@ -49,8 +50,14 @@ func AddBuildSubcommand(app *clir.Cli, w io.Writer) {
|
||||
command.StringFlag("upxflags", "Flags to pass to upx", &compressFlags)
|
||||
|
||||
// Setup Platform flag
|
||||
platform := runtime.GOOS
|
||||
command.StringFlag("platform", "Platform to target", &platform)
|
||||
platform := runtime.GOOS + "/"
|
||||
if system.IsAppleSilicon {
|
||||
platform += "arm64"
|
||||
} else {
|
||||
platform += runtime.GOARCH
|
||||
}
|
||||
|
||||
command.StringFlag("platform", "Platform to target. Comma separate multiple platforms", &platform)
|
||||
|
||||
// Verbosity
|
||||
verbosity := 1
|
||||
@@ -103,28 +110,6 @@ func AddBuildSubcommand(app *clir.Cli, w io.Writer) {
|
||||
app.PrintBanner()
|
||||
}
|
||||
|
||||
// Check platform
|
||||
validPlatformArch := slicer.String([]string{
|
||||
"darwin",
|
||||
"darwin/amd64",
|
||||
"darwin/arm64",
|
||||
"darwin/universal",
|
||||
"linux",
|
||||
//"linux/amd64",
|
||||
//"linux/arm-7",
|
||||
"windows",
|
||||
"windows/amd64",
|
||||
"windows/arm64",
|
||||
})
|
||||
if !validPlatformArch.Contains(platform) {
|
||||
return fmt.Errorf("platform %s is not supported. Platforms supported: %s", platform, validPlatformArch.Join(","))
|
||||
}
|
||||
|
||||
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 {
|
||||
@@ -174,6 +159,10 @@ func AddBuildSubcommand(app *clir.Cli, w io.Writer) {
|
||||
modeString = "Debug"
|
||||
}
|
||||
|
||||
var targets slicer.StringSlicer
|
||||
targets.AddSlice(strings.Split(platform, ","))
|
||||
targets.Deduplicate()
|
||||
|
||||
// Create BuildOptions
|
||||
buildOptions := &build.Options{
|
||||
Logger: logger,
|
||||
@@ -194,27 +183,13 @@ func AddBuildSubcommand(app *clir.Cli, w io.Writer) {
|
||||
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, "Platforms: \t%s\n", platform)
|
||||
fmt.Fprintf(w, "Compiler: \t%s\n", compilerPath)
|
||||
fmt.Fprintf(w, "Build Mode: \t%s\n", modeString)
|
||||
fmt.Fprintf(w, "Skip Frontend: \t%t\n", skipFrontend)
|
||||
@@ -223,7 +198,7 @@ func AddBuildSubcommand(app *clir.Cli, w io.Writer) {
|
||||
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 {
|
||||
if len(buildOptions.OutputFile) > 0 && targets.Length() == 1 {
|
||||
fmt.Fprintf(w, "Output File: \t%s\n", buildOptions.OutputFile)
|
||||
}
|
||||
fmt.Fprintf(w, "\n")
|
||||
@@ -234,30 +209,109 @@ func AddBuildSubcommand(app *clir.Cli, w io.Writer) {
|
||||
return err
|
||||
}
|
||||
|
||||
return doBuild(buildOptions)
|
||||
cwd, err := os.Getwd()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
projectOptions, err := project.Load(cwd)
|
||||
|
||||
// Check platform
|
||||
validPlatformArch := slicer.String([]string{
|
||||
"darwin",
|
||||
"darwin/amd64",
|
||||
"darwin/arm64",
|
||||
"darwin/universal",
|
||||
"linux",
|
||||
"linux/amd64",
|
||||
"linux/arm64",
|
||||
"windows",
|
||||
"windows/amd64",
|
||||
"windows/arm64",
|
||||
})
|
||||
|
||||
targets.Each(func(platform string) {
|
||||
|
||||
if !validPlatformArch.Contains(platform) {
|
||||
buildOptions.Logger.Println("platform '%s' is not supported - skipping. Supported platforms: %s", platform, validPlatformArch.Join(","))
|
||||
return
|
||||
}
|
||||
|
||||
desiredFilename := projectOptions.OutputFilename
|
||||
if desiredFilename == "" {
|
||||
desiredFilename = projectOptions.Name
|
||||
}
|
||||
desiredFilename = strings.TrimSuffix(desiredFilename, ".exe")
|
||||
|
||||
// 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]
|
||||
}
|
||||
|
||||
banner := "Building target: " + platform
|
||||
logger.Println(banner)
|
||||
logger.Println(strings.Repeat("-", len(banner)))
|
||||
|
||||
if compress && platform == "darwin/universal" {
|
||||
logger.Println("Warning: compress flag unsupported for universal binaries. Ignoring.")
|
||||
compress = false
|
||||
}
|
||||
|
||||
switch buildOptions.Platform {
|
||||
case "darwin":
|
||||
if runtime.GOOS != "darwin" {
|
||||
logger.Println("Crosscompiling to Mac not currently supported.\n")
|
||||
return
|
||||
}
|
||||
macTargets := targets.Filter(func(platform string) bool {
|
||||
return strings.HasPrefix(platform, "darwin")
|
||||
})
|
||||
if macTargets.Length() == 2 {
|
||||
buildOptions.BundleName = fmt.Sprintf("%s-%s.app", desiredFilename, buildOptions.Arch)
|
||||
}
|
||||
}
|
||||
|
||||
if targets.Length() > 1 {
|
||||
// target filename
|
||||
switch buildOptions.Platform {
|
||||
case "windows":
|
||||
desiredFilename = fmt.Sprintf("%s-%s", desiredFilename, buildOptions.Arch)
|
||||
case "linux", "darwin":
|
||||
desiredFilename = fmt.Sprintf("%s-%s-%s", desiredFilename, buildOptions.Platform, buildOptions.Arch)
|
||||
}
|
||||
}
|
||||
if buildOptions.Platform == "windows" {
|
||||
desiredFilename += ".exe"
|
||||
}
|
||||
buildOptions.OutputFile = desiredFilename
|
||||
|
||||
// Start Time
|
||||
start := time.Now()
|
||||
|
||||
outputFilename, err := build.Build(buildOptions)
|
||||
if err != nil {
|
||||
logger.Println("Error: ", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
// Subsequent iterations
|
||||
buildOptions.IgnoreFrontend = true
|
||||
buildOptions.CleanBuildDirectory = false
|
||||
|
||||
// Output stats
|
||||
buildOptions.Logger.Println(fmt.Sprintf("Built '%s' in %s.\n", outputFilename, time.Since(start).Round(time.Millisecond).String()))
|
||||
|
||||
})
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
func checkGoModVersion(logger *clilogger.CLILogger, updateGoMod bool) error {
|
||||
cwd, err := os.Getwd()
|
||||
if err != nil {
|
||||
|
||||
@@ -7,15 +7,15 @@ require (
|
||||
github.com/fatih/structtag v1.2.0
|
||||
github.com/flytam/filenamify v1.0.0
|
||||
github.com/fsnotify/fsnotify v1.4.9
|
||||
github.com/fsouza/go-dockerclient v1.7.8
|
||||
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/shlex v0.0.0-20191202100458-e7afc7fbc510
|
||||
github.com/google/uuid v1.1.2 // indirect
|
||||
github.com/gorilla/websocket v1.4.1
|
||||
github.com/google/uuid v1.2.0 // indirect
|
||||
github.com/gorilla/websocket v1.4.2
|
||||
github.com/imdario/mergo v0.3.12
|
||||
github.com/jackmordaunt/icns v1.0.0
|
||||
github.com/leaanthony/clir v1.0.4
|
||||
@@ -27,7 +27,7 @@ require (
|
||||
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/winc v0.0.0-20220202120322-32d63aaf77de
|
||||
github.com/leaanthony/winc v0.0.0-20220208061147-37b059b9dc3b
|
||||
github.com/leaanthony/winicon v1.0.0
|
||||
github.com/matryer/is v1.4.0
|
||||
github.com/olekukonko/tablewriter v0.0.4
|
||||
@@ -40,21 +40,29 @@ require (
|
||||
github.com/tidwall/sjson v1.1.7
|
||||
github.com/wzshiming/ctc v1.2.3
|
||||
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/mod v0.4.2
|
||||
golang.org/x/net v0.0.0-20211216030914-fe4d6282115f
|
||||
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9
|
||||
golang.org/x/tools v0.1.0
|
||||
golang.org/x/tools v0.1.5
|
||||
nhooyr.io/websocket v1.8.6
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/Microsoft/go-winio v0.4.16 // indirect
|
||||
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect
|
||||
github.com/Microsoft/go-winio v0.5.1 // indirect
|
||||
github.com/Microsoft/hcsshim v0.9.2 // indirect
|
||||
github.com/andybalholm/brotli v1.0.2 // indirect
|
||||
github.com/containerd/cgroups v1.0.3 // indirect
|
||||
github.com/containerd/containerd v1.6.0 // indirect
|
||||
github.com/docker/docker v20.10.12+incompatible // indirect
|
||||
github.com/docker/go-connections v0.4.0 // indirect
|
||||
github.com/docker/go-units v0.4.0 // 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.6 // indirect
|
||||
github.com/google/go-cmp v0.5.5 // indirect
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // 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
|
||||
@@ -63,9 +71,17 @@ require (
|
||||
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/moby/sys/mount v0.2.0 // indirect
|
||||
github.com/moby/sys/mountinfo v0.5.0 // indirect
|
||||
github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 // indirect
|
||||
github.com/morikuni/aec v1.0.0 // indirect
|
||||
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // indirect
|
||||
github.com/opencontainers/go-digest v1.0.0 // indirect
|
||||
github.com/opencontainers/image-spec v1.0.2 // indirect
|
||||
github.com/opencontainers/runc v1.1.0 // indirect
|
||||
github.com/savsgio/gotils v0.0.0-20200117113501-90175b0fbe3f // indirect
|
||||
github.com/sergi/go-diff v1.1.0 // indirect
|
||||
github.com/sirupsen/logrus v1.8.1 // 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
|
||||
@@ -75,8 +91,10 @@ require (
|
||||
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
|
||||
go.opencensus.io v0.23.0 // indirect
|
||||
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 // 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
|
||||
gotest.tools/v3 v3.1.0 // indirect
|
||||
)
|
||||
|
||||
@@ -81,8 +81,8 @@ func CreateApp(appoptions *options.App) (*App, error) {
|
||||
debug := IsDebug()
|
||||
ctx = context.WithValue(ctx, "debug", debug)
|
||||
// Attach logger to context
|
||||
ctx = context.WithValue(ctx, "logger", myLogger)
|
||||
if debug {
|
||||
ctx = context.WithValue(ctx, "logger", myLogger)
|
||||
ctx = context.WithValue(ctx, "buildtype", "debug")
|
||||
} else {
|
||||
ctx = context.WithValue(ctx, "buildtype", "production")
|
||||
|
||||
@@ -106,8 +106,8 @@ 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) WindowUnfullscreen() {
|
||||
b.session.log.Info("WindowUnfullscreen unsupported in Bridge mode")
|
||||
}
|
||||
|
||||
func (b BridgeClient) WindowSetColour(colour int) {
|
||||
|
||||
@@ -2,11 +2,12 @@ package bridge
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/wailsapp/wails/v2/pkg/runtime"
|
||||
"os/exec"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/wailsapp/wails/v2/pkg/runtime"
|
||||
|
||||
"github.com/wailsapp/wails/v2/internal/messagedispatcher"
|
||||
|
||||
"github.com/wailsapp/wails/v2/internal/logger"
|
||||
@@ -126,7 +127,7 @@ func (d *DialogClient) WindowSetMaxSize(width int, height int) {
|
||||
func (d *DialogClient) WindowFullscreen() {
|
||||
}
|
||||
|
||||
func (d *DialogClient) WindowUnFullscreen() {
|
||||
func (d *DialogClient) WindowUnfullscreen() {
|
||||
}
|
||||
|
||||
func (d *DialogClient) WindowSetColour(colour int) {
|
||||
|
||||
@@ -0,0 +1,148 @@
|
||||
package docker
|
||||
|
||||
import (
|
||||
"context"
|
||||
dc "github.com/fsouza/go-dockerclient"
|
||||
"io"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func CrossCompile(projectPath string, outputfilename string, platform string, verbose bool, loggerWriter io.Writer) error {
|
||||
|
||||
client, err := dc.NewClientFromEnv()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
tag := strings.ReplaceAll(platform, "/", "-")
|
||||
|
||||
outputStream := io.Discard
|
||||
if verbose {
|
||||
outputStream = loggerWriter
|
||||
}
|
||||
|
||||
err = client.PullImage(dc.PullImageOptions{
|
||||
All: false,
|
||||
Repository: "wailsapp/cc",
|
||||
Tag: tag,
|
||||
Platform: "",
|
||||
Registry: "",
|
||||
OutputStream: outputStream,
|
||||
RawJSONStream: false,
|
||||
InactivityTimeout: 0,
|
||||
Context: context.Background(),
|
||||
}, dc.AuthConfiguration{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
projectDir := projectPath + ":/usr/src/myapp:rw"
|
||||
env := []string{"CGO_ENABLED=1"}
|
||||
if platform == "linux/arm64" {
|
||||
env = append(env, "CC_FOR_TARGET=aarch64-linux-gnu-gcc", "PKG_CONFIG_PATH=/usr/lib/aarch64-linux-gnu/pkgconfig")
|
||||
}
|
||||
|
||||
container, err := client.CreateContainer(dc.CreateContainerOptions{
|
||||
//Name: "wails-" + tag + "-builder",
|
||||
Config: &dc.Config{
|
||||
Env: env,
|
||||
Cmd: []string{"go", "build", "-x", "-tags", "desktop,production", "-o", "build/bin/" + outputfilename},
|
||||
Image: "wailsapp/cc:" + tag,
|
||||
WorkingDir: "/usr/src/myapp",
|
||||
AttachStdin: false,
|
||||
AttachStdout: verbose,
|
||||
AttachStderr: verbose,
|
||||
ArgsEscaped: false,
|
||||
},
|
||||
HostConfig: &dc.HostConfig{
|
||||
Binds: []string{projectDir},
|
||||
Privileged: true,
|
||||
AutoRemove: false,
|
||||
},
|
||||
NetworkingConfig: nil,
|
||||
Context: nil,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = client.StartContainer(container.ID, &dc.HostConfig{
|
||||
Privileged: true,
|
||||
AutoRemove: false,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
statusCode, err := client.WaitContainer(container.ID)
|
||||
if statusCode != 0 {
|
||||
return err
|
||||
}
|
||||
|
||||
/*
|
||||
client, err := client.NewClientWithOpts(client.FromEnv)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error from Docker1: %v", err)
|
||||
}
|
||||
|
||||
|
||||
ctx := context.Background()
|
||||
pulloutput, err := client.ImagePull(ctx, image, types.ImagePullOptions{})
|
||||
defer pulloutput.Close()
|
||||
output := loggerWriter
|
||||
if output == nil {
|
||||
output = os.Stdout
|
||||
}
|
||||
_, _ = io.Copy(output, pulloutput)
|
||||
//if err != nil {
|
||||
// if verbose {
|
||||
// println("here")
|
||||
//
|
||||
//
|
||||
// }
|
||||
// return fmt.Errorf("error from Docker2: %v", err)
|
||||
//}
|
||||
resp, err := client.ContainerCreate(ctx, &container.Config{
|
||||
AttachStdout: verbose,
|
||||
AttachStderr: verbose,
|
||||
Image: image,
|
||||
Env: []string{"CGO_ENABLED=1"},
|
||||
Cmd: []string{"go", "build", "-tags", "desktop,production"},
|
||||
}, &container.HostConfig{
|
||||
Mounts: []mount.Mount{
|
||||
{
|
||||
Type: mount.TypeBind,
|
||||
Source: projectPath,
|
||||
Target: "/usr/src/myapp",
|
||||
},
|
||||
},
|
||||
}, nil, nil, "")
|
||||
if err != nil {
|
||||
return fmt.Errorf("error from Docker3: %v", err)
|
||||
}
|
||||
|
||||
err = client.ContainerStart(ctx, resp.ID, types.ContainerStartOptions{})
|
||||
if err != nil {
|
||||
return fmt.Errorf("error from Docker4: %v", err)
|
||||
}
|
||||
|
||||
statusCh, errCh := client.ContainerWait(ctx, resp.ID, container.WaitConditionNotRunning)
|
||||
select {
|
||||
case err := <-errCh:
|
||||
if err != nil {
|
||||
return fmt.Errorf("error from Docker5: %v", err)
|
||||
}
|
||||
case <-statusCh:
|
||||
}
|
||||
|
||||
if verbose {
|
||||
out, err := client.ContainerLogs(ctx, resp.ID, types.ContainerLogsOptions{ShowStdout: true})
|
||||
if err != nil {
|
||||
return fmt.Errorf("error from Docke6r: %v", err)
|
||||
}
|
||||
|
||||
_, _ = stdcopy.StdCopy(os.Stdout, os.Stderr, out)
|
||||
}
|
||||
*/
|
||||
return nil
|
||||
}
|
||||
@@ -61,8 +61,8 @@ func (c *Client) WindowFullscreen() {
|
||||
C.Fullscreen(c.app.app)
|
||||
}
|
||||
|
||||
// WindowUnFullscreen will unfullscreen the window
|
||||
func (c *Client) WindowUnFullscreen() {
|
||||
// WindowUnfullscreen will unfullscreen the window
|
||||
func (c *Client) WindowUnfullscreen() {
|
||||
C.UnFullscreen(c.app.app)
|
||||
}
|
||||
|
||||
@@ -141,8 +141,6 @@ func (c *Client) OpenFileDialog(dialogOptions runtime.OpenDialogOptions, callbac
|
||||
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),
|
||||
@@ -189,8 +187,6 @@ func (c *Client) OpenMultipleFilesDialog(dialogOptions runtime.OpenDialogOptions
|
||||
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),
|
||||
@@ -239,7 +235,6 @@ func (c *Client) MessageDialog(dialogOptions runtime.MessageDialogOptions, callb
|
||||
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]),
|
||||
|
||||
@@ -10,13 +10,14 @@ 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/leaanthony/go-common-file-dialog/cfd"
|
||||
"github.com/wailsapp/wails/v2/pkg/runtime"
|
||||
"golang.org/x/sys/windows"
|
||||
|
||||
"github.com/wailsapp/wails/v2/internal/logger"
|
||||
)
|
||||
|
||||
@@ -63,8 +64,8 @@ func (c *Client) WindowFullscreen() {
|
||||
C.Fullscreen(c.app.app)
|
||||
}
|
||||
|
||||
// WindowUnFullscreen will unfullscreen the window
|
||||
func (c *Client) WindowUnFullscreen() {
|
||||
// WindowUnfullscreen will unfullscreen the window
|
||||
func (c *Client) WindowUnfullscreen() {
|
||||
C.UnFullscreen(c.app.app)
|
||||
}
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@ void Fullscreen(void* ctx);
|
||||
void UnFullscreen(void* ctx);
|
||||
void Minimise(void* ctx);
|
||||
void UnMinimise(void* ctx);
|
||||
void ToggleMaximise(void* ctx);
|
||||
void Maximise(void* ctx);
|
||||
void UnMaximise(void* ctx);
|
||||
void Hide(void* ctx);
|
||||
|
||||
@@ -156,6 +156,13 @@ void Maximise(void* inctx) {
|
||||
);
|
||||
}
|
||||
|
||||
void ToggleMaximise(void* inctx) {
|
||||
WailsContext *ctx = (__bridge WailsContext*) inctx;
|
||||
ON_MAIN_THREAD(
|
||||
[ctx ToggleMaximise];
|
||||
);
|
||||
}
|
||||
|
||||
const char* GetSize(void *inctx) {
|
||||
WailsContext *ctx = (__bridge WailsContext*) inctx;
|
||||
NSRect frame = [ctx.mainWindow frame];
|
||||
|
||||
@@ -67,6 +67,7 @@
|
||||
- (void) Minimise;
|
||||
- (void) UnMinimise;
|
||||
- (void) Maximise;
|
||||
- (void) ToggleMaximise;
|
||||
- (void) UnMaximise;
|
||||
- (void) SetRGBA:(int)r :(int)g :(int)b :(int)a;
|
||||
- (void) HideMouse;
|
||||
|
||||
@@ -322,11 +322,6 @@
|
||||
return (mask & NSWindowStyleMaskFullScreen) == NSWindowStyleMaskFullScreen;
|
||||
}
|
||||
|
||||
- (bool) isMaximised {
|
||||
long mask = [self.mainWindow styleMask];
|
||||
return (mask & NSWindowStyleMaskFullScreen) == NSWindowStyleMaskFullScreen;
|
||||
}
|
||||
|
||||
// Fullscreen sets the main window to be fullscreen
|
||||
- (void) Fullscreen {
|
||||
if( ! [self isFullScreen] ) {
|
||||
@@ -366,6 +361,10 @@
|
||||
}
|
||||
}
|
||||
|
||||
- (void) ToggleMaximise {
|
||||
[self.mainWindow zoom:nil];
|
||||
}
|
||||
|
||||
- (void) UnMaximise {
|
||||
if ([self.mainWindow isZoomed]) {
|
||||
[self.mainWindow zoom:nil];
|
||||
|
||||
@@ -167,7 +167,7 @@ func (f *Frontend) WindowFullscreen() {
|
||||
f.mainWindow.Fullscreen()
|
||||
}
|
||||
|
||||
func (f *Frontend) WindowUnFullscreen() {
|
||||
func (f *Frontend) WindowUnfullscreen() {
|
||||
f.mainWindow.UnFullscreen()
|
||||
}
|
||||
|
||||
@@ -181,6 +181,9 @@ func (f *Frontend) WindowHide() {
|
||||
func (f *Frontend) WindowMaximise() {
|
||||
f.mainWindow.Maximise()
|
||||
}
|
||||
func (f *Frontend) WindowToggleMaximise() {
|
||||
f.mainWindow.ToggleMaximise()
|
||||
}
|
||||
func (f *Frontend) WindowUnmaximise() {
|
||||
f.mainWindow.UnMaximise()
|
||||
}
|
||||
|
||||
@@ -154,6 +154,9 @@ func (w *Window) SetTitle(title string) {
|
||||
func (w *Window) Maximise() {
|
||||
C.Maximise(w.context)
|
||||
}
|
||||
func (w *Window) ToggleMaximise() {
|
||||
C.ToggleMaximise(w.context)
|
||||
}
|
||||
|
||||
func (w *Window) UnMaximise() {
|
||||
C.UnMaximise(w.context)
|
||||
|
||||
@@ -43,8 +43,7 @@ type Frontend struct {
|
||||
startURL string
|
||||
|
||||
// main window handle
|
||||
mainWindow *Window
|
||||
// minWidth, minHeight, maxWidth, maxHeight int
|
||||
mainWindow *Window
|
||||
bindings *binding.Bindings
|
||||
dispatcher frontend.Dispatcher
|
||||
servingFromDisk bool
|
||||
@@ -160,7 +159,7 @@ func (f *Frontend) WindowFullscreen() {
|
||||
f.mainWindow.Fullscreen()
|
||||
}
|
||||
|
||||
func (f *Frontend) WindowUnFullscreen() {
|
||||
func (f *Frontend) WindowUnfullscreen() {
|
||||
f.mainWindow.UnFullscreen()
|
||||
}
|
||||
|
||||
@@ -174,6 +173,9 @@ func (f *Frontend) WindowHide() {
|
||||
func (f *Frontend) WindowMaximise() {
|
||||
f.mainWindow.Maximise()
|
||||
}
|
||||
func (f *Frontend) WindowToggleMaximise() {
|
||||
f.mainWindow.ToggleMaximise()
|
||||
}
|
||||
func (f *Frontend) WindowUnmaximise() {
|
||||
f.mainWindow.UnMaximise()
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ package linux
|
||||
#include "webkit2/webkit2.h"
|
||||
#include <stdio.h>
|
||||
#include <limits.h>
|
||||
#include "stdint.h"
|
||||
|
||||
|
||||
void ExecuteOnMainThread(void* f, gpointer jscallback) {
|
||||
@@ -32,25 +33,15 @@ static GtkBox* GTKBOX(void *pointer) {
|
||||
return GTK_BOX(pointer);
|
||||
}
|
||||
|
||||
static void SetMinSize(GtkWindow* window, int width, int height) {
|
||||
GdkGeometry size;
|
||||
size.min_height = height;
|
||||
size.min_width = width;
|
||||
gtk_window_set_geometry_hints(window, NULL, &size, GDK_HINT_MIN_SIZE);
|
||||
}
|
||||
|
||||
static void SetMaxSize(GtkWindow* window, int width, int height) {
|
||||
GdkGeometry size;
|
||||
if( width == 0 ) {
|
||||
width = INT_MAX;
|
||||
}
|
||||
if( height == 0 ) {
|
||||
height = INT_MAX;
|
||||
}
|
||||
|
||||
size.max_height = height;
|
||||
size.max_width = width;
|
||||
gtk_window_set_geometry_hints(window, NULL, &size, GDK_HINT_MAX_SIZE);
|
||||
static void SetMinMaxSize(GtkWindow* window, int min_width, int min_height, int max_width, int max_height) {
|
||||
GdkGeometry size;
|
||||
size.min_width = size.min_height = size.max_width = size.max_height = 0;
|
||||
int flags = GDK_HINT_MAX_SIZE | GDK_HINT_MIN_SIZE;
|
||||
size.max_height = (max_height == 0 ? INT_MAX : max_height);
|
||||
size.max_width = (max_width == 0 ? INT_MAX : max_width);
|
||||
size.min_height = min_height;
|
||||
size.min_width = min_width;
|
||||
gtk_window_set_geometry_hints(window, NULL, &size, flags);
|
||||
}
|
||||
|
||||
GdkRectangle getCurrentMonitorGeometry(GtkWindow *window) {
|
||||
@@ -89,6 +80,13 @@ int IsFullscreen(GtkWidget *widget) {
|
||||
return state & GDK_WINDOW_STATE_FULLSCREEN == GDK_WINDOW_STATE_FULLSCREEN;
|
||||
}
|
||||
|
||||
int IsMaximised(GtkWidget *widget) {
|
||||
GdkWindow *gdkwindow = gtk_widget_get_window(widget);
|
||||
GdkWindowState state = gdk_window_get_state(GDK_WINDOW(gdkwindow));
|
||||
return state & GDK_WINDOW_STATE_MAXIMIZED;
|
||||
}
|
||||
|
||||
|
||||
extern void processMessage(char*);
|
||||
|
||||
static void sendMessageToBackend(WebKitUserContentManager *contentManager,
|
||||
@@ -120,6 +118,7 @@ ulong setupInvokeSignal(void* contentManager) {
|
||||
float xroot = 0.0f;
|
||||
float yroot = 0.0f;
|
||||
int dragTime = -1;
|
||||
bool contextMenuDisabled = false;
|
||||
|
||||
gboolean buttonPress(GtkWidget *widget, GdkEventButton *event, void* dummy)
|
||||
{
|
||||
@@ -128,12 +127,18 @@ gboolean buttonPress(GtkWidget *widget, GdkEventButton *event, void* dummy)
|
||||
dragTime = -1;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if( event->button == 3 && contextMenuDisabled ) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (event->type == GDK_BUTTON_PRESS && event->button == 1)
|
||||
{
|
||||
xroot = event->x_root;
|
||||
yroot = event->y_root;
|
||||
dragTime = event->time;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@@ -447,6 +452,38 @@ void SetPosition(void* window, int x, int y) {
|
||||
ExecuteOnMainThread(setPosition, (gpointer)args);
|
||||
}
|
||||
|
||||
void Show(gpointer data) {
|
||||
gtk_widget_show((GtkWidget*)data);
|
||||
}
|
||||
|
||||
void Hide(gpointer data) {
|
||||
gtk_widget_hide((GtkWidget*)data);
|
||||
}
|
||||
|
||||
void Maximise(gpointer data) {
|
||||
gtk_window_maximize((GtkWindow*)data);
|
||||
}
|
||||
|
||||
void UnMaximise(gpointer data) {
|
||||
gtk_window_unmaximize((GtkWindow*)data);
|
||||
}
|
||||
|
||||
void Minimise(gpointer data) {
|
||||
gtk_window_iconify((GtkWindow*)data);
|
||||
}
|
||||
|
||||
void UnMinimise(gpointer data) {
|
||||
gtk_window_present((GtkWindow*)data);
|
||||
}
|
||||
|
||||
bool disableContextMenu(GtkWindow* window) {
|
||||
return TRUE;
|
||||
}
|
||||
void DisableContextMenu(void* webview) {
|
||||
contextMenuDisabled = TRUE;
|
||||
g_signal_connect(WEBKIT_WEB_VIEW(webview), "context-menu", G_CALLBACK(disableContextMenu), NULL);
|
||||
}
|
||||
|
||||
|
||||
*/
|
||||
import "C"
|
||||
@@ -466,15 +503,16 @@ func gtkBool(input bool) C.gboolean {
|
||||
}
|
||||
|
||||
type Window struct {
|
||||
appoptions *options.App
|
||||
debug bool
|
||||
gtkWindow unsafe.Pointer
|
||||
contentManager unsafe.Pointer
|
||||
webview unsafe.Pointer
|
||||
applicationMenu *menu.Menu
|
||||
menubar *C.GtkWidget
|
||||
vbox *C.GtkWidget
|
||||
accels *C.GtkAccelGroup
|
||||
appoptions *options.App
|
||||
debug bool
|
||||
gtkWindow unsafe.Pointer
|
||||
contentManager unsafe.Pointer
|
||||
webview unsafe.Pointer
|
||||
applicationMenu *menu.Menu
|
||||
menubar *C.GtkWidget
|
||||
vbox *C.GtkWidget
|
||||
accels *C.GtkAccelGroup
|
||||
minWidth, minHeight, maxWidth, maxHeight int
|
||||
}
|
||||
|
||||
func bool2Cint(value bool) C.int {
|
||||
@@ -489,6 +527,10 @@ func NewWindow(appoptions *options.App, debug bool) *Window {
|
||||
result := &Window{
|
||||
appoptions: appoptions,
|
||||
debug: debug,
|
||||
minHeight: appoptions.MinHeight,
|
||||
minWidth: appoptions.MinWidth,
|
||||
maxHeight: appoptions.MaxHeight,
|
||||
maxWidth: appoptions.MaxWidth,
|
||||
}
|
||||
|
||||
gtkWindow := C.gtk_window_new(C.GTK_WINDOW_TOPLEVEL)
|
||||
@@ -512,6 +554,8 @@ func NewWindow(appoptions *options.App, debug bool) *Window {
|
||||
|
||||
if debug {
|
||||
C.devtoolsEnabled(unsafe.Pointer(webview), C.int(1))
|
||||
} else {
|
||||
C.DisableContextMenu(unsafe.Pointer(webview))
|
||||
}
|
||||
|
||||
// Set background colour
|
||||
@@ -550,11 +594,17 @@ func (w *Window) cWebKitUserContentManager() *C.WebKitUserContentManager {
|
||||
}
|
||||
|
||||
func (w *Window) Fullscreen() {
|
||||
C.SetMinMaxSize(w.asGTKWindow(), C.int(0), C.int(0), C.int(0), C.int(0))
|
||||
C.ExecuteOnMainThread(C.gtk_window_fullscreen, C.gpointer(w.asGTKWindow()))
|
||||
}
|
||||
|
||||
func (w *Window) UnFullscreen() {
|
||||
if !w.IsFullScreen() {
|
||||
return
|
||||
}
|
||||
C.ExecuteOnMainThread(C.gtk_window_unfullscreen, C.gpointer(w.asGTKWindow()))
|
||||
w.SetMinSize(w.minWidth, w.minHeight)
|
||||
w.SetMaxSize(w.maxWidth, w.maxHeight)
|
||||
}
|
||||
|
||||
func (w *Window) Destroy() {
|
||||
@@ -587,35 +637,39 @@ func (w *Window) GetPosition() (int, int) {
|
||||
}
|
||||
|
||||
func (w *Window) SetMaxSize(maxWidth int, maxHeight int) {
|
||||
C.SetMaxSize(w.asGTKWindow(), C.int(maxWidth), C.int(maxHeight))
|
||||
w.maxHeight = maxHeight
|
||||
w.maxWidth = maxWidth
|
||||
C.SetMinMaxSize(w.asGTKWindow(), C.int(w.minWidth), C.int(w.minHeight), C.int(w.maxWidth), C.int(w.maxHeight))
|
||||
}
|
||||
|
||||
func (w *Window) SetMinSize(minWidth int, minHeight int) {
|
||||
C.SetMinSize(w.asGTKWindow(), C.int(minWidth), C.int(minHeight))
|
||||
w.minHeight = minHeight
|
||||
w.minWidth = minWidth
|
||||
C.SetMinMaxSize(w.asGTKWindow(), C.int(w.minWidth), C.int(w.minHeight), C.int(w.maxWidth), C.int(w.maxHeight))
|
||||
}
|
||||
|
||||
func (w *Window) Show() {
|
||||
C.gtk_widget_show(w.asGTKWidget())
|
||||
C.ExecuteOnMainThread(C.Show, C.gpointer(w.asGTKWindow()))
|
||||
}
|
||||
|
||||
func (w *Window) Hide() {
|
||||
C.gtk_widget_hide(w.asGTKWidget())
|
||||
C.ExecuteOnMainThread(C.Hide, C.gpointer(w.asGTKWindow()))
|
||||
}
|
||||
|
||||
func (w *Window) Maximise() {
|
||||
C.gtk_window_maximize(w.asGTKWindow())
|
||||
C.ExecuteOnMainThread(C.Maximise, C.gpointer(w.asGTKWindow()))
|
||||
}
|
||||
|
||||
func (w *Window) UnMaximise() {
|
||||
C.gtk_window_unmaximize(w.asGTKWindow())
|
||||
C.ExecuteOnMainThread(C.UnMaximise, C.gpointer(w.asGTKWindow()))
|
||||
}
|
||||
|
||||
func (w *Window) Minimise() {
|
||||
C.gtk_window_iconify(w.asGTKWindow())
|
||||
C.ExecuteOnMainThread(C.Minimise, C.gpointer(w.asGTKWindow()))
|
||||
}
|
||||
|
||||
func (w *Window) UnMinimise() {
|
||||
C.gtk_window_present(w.asGTKWindow())
|
||||
C.ExecuteOnMainThread(C.UnMinimise, C.gpointer(w.asGTKWindow()))
|
||||
}
|
||||
|
||||
func (w *Window) IsFullScreen() bool {
|
||||
@@ -626,6 +680,11 @@ func (w *Window) IsFullScreen() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (w *Window) IsMaximised() bool {
|
||||
result := C.IsMaximised(w.asGTKWidget())
|
||||
return result > 0
|
||||
}
|
||||
|
||||
func (w *Window) SetRGBA(r uint8, g uint8, b uint8, a uint8) {
|
||||
data := C.RGBAOptions{
|
||||
r: C.uchar(r),
|
||||
@@ -766,3 +825,11 @@ func (w *Window) MessageDialog(dialogOptions frontend.MessageDialogOptions) {
|
||||
}
|
||||
C.ExecuteOnMainThread(C.messageDialog, C.gpointer(&data))
|
||||
}
|
||||
|
||||
func (w *Window) ToggleMaximise() {
|
||||
if w.IsMaximised() {
|
||||
w.UnMaximise()
|
||||
} else {
|
||||
w.Maximise()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,11 +40,10 @@ type Frontend struct {
|
||||
startURL string
|
||||
|
||||
// main window handle
|
||||
mainWindow *Window
|
||||
minWidth, minHeight, maxWidth, maxHeight int
|
||||
bindings *binding.Bindings
|
||||
dispatcher frontend.Dispatcher
|
||||
servingFromDisk bool
|
||||
mainWindow *Window
|
||||
bindings *binding.Bindings
|
||||
dispatcher frontend.Dispatcher
|
||||
servingFromDisk bool
|
||||
|
||||
hasStarted bool
|
||||
}
|
||||
@@ -57,10 +56,6 @@ func NewFrontend(ctx context.Context, appoptions *options.App, myLogger *logger.
|
||||
bindings: appBindings,
|
||||
dispatcher: dispatcher,
|
||||
ctx: ctx,
|
||||
minHeight: appoptions.MinHeight,
|
||||
minWidth: appoptions.MinWidth,
|
||||
maxHeight: appoptions.MaxHeight,
|
||||
maxWidth: appoptions.MaxWidth,
|
||||
startURL: "file://wails/",
|
||||
}
|
||||
|
||||
@@ -171,22 +166,18 @@ func (f *Frontend) WindowSetTitle(title string) {
|
||||
|
||||
func (f *Frontend) WindowFullscreen() {
|
||||
runtime.LockOSThread()
|
||||
f.mainWindow.SetMaxSize(0, 0)
|
||||
f.mainWindow.SetMinSize(0, 0)
|
||||
if f.frontendOptions.Frameless && f.frontendOptions.DisableResize == false {
|
||||
f.ExecJS("window.wails.flags.enableResize = false;")
|
||||
}
|
||||
f.mainWindow.Fullscreen()
|
||||
}
|
||||
|
||||
func (f *Frontend) WindowUnFullscreen() {
|
||||
func (f *Frontend) WindowUnfullscreen() {
|
||||
runtime.LockOSThread()
|
||||
if f.frontendOptions.Frameless && f.frontendOptions.DisableResize == false {
|
||||
f.ExecJS("window.wails.flags.enableResize = true;")
|
||||
}
|
||||
f.mainWindow.UnFullscreen()
|
||||
f.mainWindow.SetMaxSize(f.maxWidth, f.maxHeight)
|
||||
f.mainWindow.SetMinSize(f.minWidth, f.minHeight)
|
||||
}
|
||||
|
||||
func (f *Frontend) WindowShow() {
|
||||
@@ -208,6 +199,18 @@ func (f *Frontend) WindowMaximise() {
|
||||
f.frontendOptions.WindowStartState = options.Maximised
|
||||
}
|
||||
}
|
||||
func (f *Frontend) WindowToggleMaximise() {
|
||||
runtime.LockOSThread()
|
||||
if !f.hasStarted {
|
||||
return
|
||||
}
|
||||
if f.mainWindow.IsMaximised() {
|
||||
f.WindowUnmaximise()
|
||||
} else {
|
||||
f.WindowMaximise()
|
||||
}
|
||||
}
|
||||
|
||||
func (f *Frontend) WindowUnmaximise() {
|
||||
runtime.LockOSThread()
|
||||
f.mainWindow.Restore()
|
||||
@@ -227,14 +230,10 @@ func (f *Frontend) WindowUnminimise() {
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
@@ -473,7 +472,8 @@ 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)
|
||||
// Use PostMessage because we don't want to block the caller until dragging has been finished.
|
||||
w32.PostMessage(f.mainWindow.Handle(), w32.WM_NCLBUTTONDOWN, w32.HTCAPTION, 0)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -481,7 +481,8 @@ func (f *Frontend) startResize(border uintptr) error {
|
||||
if !w32.ReleaseCapture() {
|
||||
return fmt.Errorf("unable to release mouse capture")
|
||||
}
|
||||
w32.SendMessage(f.mainWindow.Handle(), w32.WM_NCLBUTTONDOWN, border, 0)
|
||||
// Use PostMessage because we don't want to block the caller until resizing has been finished.
|
||||
w32.PostMessage(f.mainWindow.Handle(), w32.WM_NCLBUTTONDOWN, border, 0)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -16,14 +16,20 @@ import (
|
||||
|
||||
type Window struct {
|
||||
winc.Form
|
||||
frontendOptions *options.App
|
||||
applicationMenu *menu.Menu
|
||||
notifyParentWindowPositionChanged func() error
|
||||
frontendOptions *options.App
|
||||
applicationMenu *menu.Menu
|
||||
notifyParentWindowPositionChanged func() error
|
||||
minWidth, minHeight, maxWidth, maxHeight int
|
||||
}
|
||||
|
||||
func NewWindow(parent winc.Controller, appoptions *options.App) *Window {
|
||||
result := new(Window)
|
||||
result.frontendOptions = appoptions
|
||||
result := &Window{
|
||||
frontendOptions: appoptions,
|
||||
minHeight: appoptions.MinHeight,
|
||||
minWidth: appoptions.MinWidth,
|
||||
maxHeight: appoptions.MaxHeight,
|
||||
maxWidth: appoptions.MaxWidth,
|
||||
}
|
||||
result.SetIsForm(true)
|
||||
|
||||
var exStyle int
|
||||
@@ -89,6 +95,33 @@ func (w *Window) Run() int {
|
||||
return winc.RunMainLoop()
|
||||
}
|
||||
|
||||
func (w *Window) Fullscreen() {
|
||||
w.Form.SetMaxSize(0, 0)
|
||||
w.Form.SetMinSize(0, 0)
|
||||
w.Form.Fullscreen()
|
||||
}
|
||||
|
||||
func (w *Window) UnFullscreen() {
|
||||
if !w.IsFullScreen() {
|
||||
return
|
||||
}
|
||||
w.Form.UnFullscreen()
|
||||
w.SetMinSize(w.minWidth, w.minHeight)
|
||||
w.SetMaxSize(w.maxWidth, w.maxHeight)
|
||||
}
|
||||
|
||||
func (w *Window) SetMinSize(minWidth int, minHeight int) {
|
||||
w.minWidth = minWidth
|
||||
w.minHeight = minHeight
|
||||
w.Form.SetMinSize(minWidth, minHeight)
|
||||
}
|
||||
|
||||
func (w *Window) SetMaxSize(maxWidth int, maxHeight int) {
|
||||
w.maxWidth = maxWidth
|
||||
w.maxHeight = maxHeight
|
||||
w.Form.SetMaxSize(maxWidth, maxHeight)
|
||||
}
|
||||
|
||||
func (w *Window) WndProc(msg uint32, wparam, lparam uintptr) uintptr {
|
||||
|
||||
switch msg {
|
||||
@@ -98,17 +131,34 @@ func (w *Window) WndProc(msg uint32, wparam, lparam uintptr) uintptr {
|
||||
if w.notifyParentWindowPositionChanged != nil {
|
||||
w.notifyParentWindowPositionChanged()
|
||||
}
|
||||
|
||||
// TODO move WM_DPICHANGED handling into winc
|
||||
case 0x02E0: //w32.WM_DPICHANGED
|
||||
newWindowSize := (*w32.RECT)(unsafe.Pointer(lparam))
|
||||
w32.SetWindowPos(w.Handle(),
|
||||
uintptr(0),
|
||||
int(newWindowSize.Left),
|
||||
int(newWindowSize.Top),
|
||||
int(newWindowSize.Right-newWindowSize.Left),
|
||||
int(newWindowSize.Bottom-newWindowSize.Top),
|
||||
w32.SWP_NOZORDER|w32.SWP_NOACTIVATE)
|
||||
}
|
||||
|
||||
if w.frontendOptions.Frameless {
|
||||
switch msg {
|
||||
case w32.WM_ACTIVATE:
|
||||
// If we want to have a frameless window but with border, extend the client area outside of the window. This
|
||||
// Option is not affected by returning 0 in WM_NCCALCSIZE.
|
||||
// As a result we have hidden the titlebar but still have the default border drawn.
|
||||
// If we want to have a frameless window but with the default frame decorations, extend the DWM client area.
|
||||
// This Option is not affected by returning 0 in WM_NCCALCSIZE.
|
||||
// As a result we have hidden the titlebar but still have the default window frame styling.
|
||||
// See: https://docs.microsoft.com/en-us/windows/win32/api/dwmapi/nf-dwmapi-dwmextendframeintoclientarea#remarks
|
||||
if winoptions := w.frontendOptions.Windows; winoptions != nil && winoptions.EnableFramelessBorder {
|
||||
if err := dwmExtendFrameIntoClientArea(w.Handle(), w32.MARGINS{-1, -1, -1, -1}); err != nil {
|
||||
if winoptions := w.frontendOptions.Windows; winoptions == nil || !winoptions.DisableFramelessWindowDecorations {
|
||||
// -1: Adds the default frame styling (aero shadow and e.g. rounded corners on Windows 11)
|
||||
// Also shows the caption buttons if transparent ant translucent but they don't work.
|
||||
// 0: Adds the default frame styling but no aero shadow, does not show the caption buttons.
|
||||
// 1: Adds the default frame styling (aero shadow and e.g. rounded corners on Windows 11) but no caption buttons
|
||||
// are shown if transparent ant translucent.
|
||||
margins := w32.MARGINS{1, 1, 1, 1} // Only extend 1 pixel to have the default frame styling but no caption buttons
|
||||
if err := dwmExtendFrameIntoClientArea(w.Handle(), margins); err != nil {
|
||||
log.Fatal(fmt.Errorf("DwmExtendFrameIntoClientArea failed: %s", err))
|
||||
}
|
||||
}
|
||||
@@ -130,6 +180,23 @@ func (w *Window) WndProc(msg uint32, wparam, lparam uintptr) uintptr {
|
||||
if w32.GetMonitorInfo(monitor, &monitorInfo) {
|
||||
rgrc := (*w32.RECT)(unsafe.Pointer(lparam))
|
||||
*rgrc = monitorInfo.RcWork
|
||||
|
||||
maxWidth := w.frontendOptions.MaxWidth
|
||||
maxHeight := w.frontendOptions.MaxHeight
|
||||
if maxWidth > 0 || maxHeight > 0 {
|
||||
var dpiX, dpiY uint
|
||||
w32.GetDPIForMonitor(monitor, w32.MDT_EFFECTIVE_DPI, &dpiX, &dpiY)
|
||||
|
||||
maxWidth := int32(winc.ScaleWithDPI(maxWidth, dpiX))
|
||||
if maxWidth > 0 && rgrc.Right-rgrc.Left > maxWidth {
|
||||
rgrc.Right = rgrc.Left + maxWidth
|
||||
}
|
||||
|
||||
maxHeight := int32(winc.ScaleWithDPI(maxHeight, dpiY))
|
||||
if maxHeight > 0 && rgrc.Bottom-rgrc.Top > maxHeight {
|
||||
rgrc.Bottom = rgrc.Top + maxHeight
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -140,6 +207,11 @@ func (w *Window) WndProc(msg uint32, wparam, lparam uintptr) uintptr {
|
||||
return w.Form.WndProc(msg, wparam, lparam)
|
||||
}
|
||||
|
||||
func (w *Window) IsMaximised() bool {
|
||||
style := uint32(w32.GetWindowLong(w.Handle(), w32.GWL_STYLE))
|
||||
return style&w32.WS_MAXIMIZE != 0
|
||||
}
|
||||
|
||||
// TODO this should be put into the winc if we are happy with this solution.
|
||||
var (
|
||||
modkernel32 = syscall.NewLazyDLL("dwmapi.dll")
|
||||
|
||||
@@ -187,6 +187,10 @@ func (d *DevWebServer) WindowMaximise() {
|
||||
d.desktopFrontend.WindowMaximise()
|
||||
}
|
||||
|
||||
func (d *DevWebServer) WindowToggleMaximise() {
|
||||
d.desktopFrontend.WindowToggleMaximise()
|
||||
}
|
||||
|
||||
func (d *DevWebServer) WindowUnmaximise() {
|
||||
d.desktopFrontend.WindowUnmaximise()
|
||||
}
|
||||
@@ -227,8 +231,8 @@ func (d *DevWebServer) WindowFullscreen() {
|
||||
d.desktopFrontend.WindowFullscreen()
|
||||
}
|
||||
|
||||
func (d *DevWebServer) WindowUnFullscreen() {
|
||||
d.desktopFrontend.WindowUnFullscreen()
|
||||
func (d *DevWebServer) WindowUnfullscreen() {
|
||||
d.desktopFrontend.WindowUnfullscreen()
|
||||
}
|
||||
|
||||
func (d *DevWebServer) WindowSetRGBA(col *options.RGBA) {
|
||||
@@ -304,7 +308,7 @@ func (d *DevWebServer) broadcast(message string) {
|
||||
d.socketMutex.Lock()
|
||||
defer d.socketMutex.Unlock()
|
||||
for client, locker := range d.websocketClients {
|
||||
go func() {
|
||||
go func(client *websocket.Conn, locker *sync.Mutex) {
|
||||
if client == nil {
|
||||
d.logger.Error("Lost connection to websocket server")
|
||||
return
|
||||
@@ -317,7 +321,7 @@ func (d *DevWebServer) broadcast(message string) {
|
||||
return
|
||||
}
|
||||
locker.Unlock()
|
||||
}()
|
||||
}(client, locker)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -339,7 +343,7 @@ func (d *DevWebServer) broadcastExcludingSender(message string, sender *websocke
|
||||
d.socketMutex.Lock()
|
||||
defer d.socketMutex.Unlock()
|
||||
for client, locker := range d.websocketClients {
|
||||
go func() {
|
||||
go func(client *websocket.Conn, locker *sync.Mutex) {
|
||||
if client == sender {
|
||||
return
|
||||
}
|
||||
@@ -351,7 +355,7 @@ func (d *DevWebServer) broadcastExcludingSender(message string, sender *websocke
|
||||
return
|
||||
}
|
||||
locker.Unlock()
|
||||
}()
|
||||
}(client, locker)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user