[v3 windows] Initial webview2 working

This commit is contained in:
Lea Anthony
2023-05-30 16:33:34 +08:00
committed by Misite Bao
parent 671dc2aa3a
commit 7e2d2a29a1
12 changed files with 642 additions and 276 deletions
+8 -9
View File
@@ -183,6 +183,8 @@ An 'X' indicates that the option is not supported by the platform.
| Hidden | Y | | | |
| EnableFraudulentWebsiteWarnings | | | | |
| Zoom | | | | |
| ZoomControlEnabled | | | | |
| OpenInspectorOnStartup | | | | |
| EnableDragAndDrop | | | | |
| Windows | Y | - | - | |
| Focused | Y | | | |
@@ -286,15 +288,14 @@ Built-in plugin support:
### Mac Options
| Feature | Default | Notes |
|-------------------|-------------------|------------------------------------------------------|
| Backdrop | MacBackdropNormal | Standard solid window |
| DisableShadow | false | |
| TitleBar | | Standard window decorations by default |
| Appearance | DefaultAppearance | |
| Feature | Default | Notes |
|-------------------------|-------------------|------------------------------------------------------|
| Backdrop | MacBackdropNormal | Standard solid window |
| DisableShadow | false | |
| TitleBar | | Standard window decorations by default |
| Appearance | DefaultAppearance | |
| InvisibleTitleBarHeight | 0 | Creates an invisible title bar for frameless windows |
## Windows Specific
- [x] Translucency
@@ -311,6 +312,4 @@ Built-in plugin support:
| DisableFramelessWindowDecorations | | |
| WindowMask | nil | Makes the window the contents of the bitmap |
## Linux Specific
+5 -1
View File
@@ -5,16 +5,20 @@ go 1.20
require github.com/wailsapp/wails/v3 v3.0.0-alpha.0
require (
github.com/go-ole/go-ole v1.2.6 // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/leaanthony/slicer v1.5.0 // indirect
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/samber/lo v1.37.0 // indirect
github.com/wailsapp/go-webview2 v1.0.1 // indirect
github.com/wailsapp/mimetype v1.4.1 // indirect
github.com/wailsapp/wails/v2 v2.3.2-0.20230117193915-45c3a501d9e6 // indirect
golang.org/x/exp v0.0.0-20220930202632-ec3f01382ef9 // indirect
golang.org/x/net v0.7.0 // indirect
golang.org/x/sys v0.7.0 // indirect
golang.org/x/sys v0.8.0 // indirect
)
replace github.com/wailsapp/wails/v3 => ../..
+12 -2
View File
@@ -1,7 +1,13 @@
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e h1:Q3+PugElBCf4PFpxhErSzU3/PY5sFL5Z6rfv4AbGAck=
github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e/go.mod h1:alcuEEnZsY1WQsagKhZDsoPCRoOijYqhZvPwLG0kzVs=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/leaanthony/slicer v1.5.0 h1:aHYTN8xbCCLxJmkNKiLB6tgcMARl4eWmH9/F+S/0HtY=
@@ -18,6 +24,8 @@ github.com/samber/lo v1.37.0/go.mod h1:9vaz2O4o8oOnK23pd2TrXufcbdbJIa3b6cstBWKpo
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
github.com/wailsapp/go-webview2 v1.0.1 h1:dEJIeEApW/MhO2tTMISZBFZPuW7kwrFA1NtgFB1z1II=
github.com/wailsapp/go-webview2 v1.0.1/go.mod h1:Uk2BePfCRzttBBjFrBmqKGJd41P6QIHeV9kTgIeOZNo=
github.com/wailsapp/mimetype v1.4.1 h1:pQN9ycO7uo4vsUUuPeHEYoUkLVkaRntMnHJxVwYhwHs=
github.com/wailsapp/mimetype v1.4.1/go.mod h1:9aV5k31bBOv5z6u+QP8TltzvNGJPmNJD4XlAL3U+j3o=
golang.org/x/exp v0.0.0-20220930202632-ec3f01382ef9 h1:RjggHMcaTVp0LOVZcW0bo8alwHrOaCrGUDgfWUHhnN4=
@@ -25,10 +33,12 @@ golang.org/x/exp v0.0.0-20220930202632-ec3f01382ef9/go.mod h1:cyybsKvd6eL0RnXn6p
golang.org/x/net v0.0.0-20210505024714-0287a6fb4125/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g=
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200810151505-1b9f1253b3ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU=
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+250 -256
View File
File diff suppressed because it is too large Load Diff
+3 -1
View File
@@ -18,8 +18,9 @@ require (
github.com/pterm/pterm v0.12.51
github.com/samber/lo v1.37.0
github.com/tc-hib/winres v0.1.6
github.com/wailsapp/go-webview2 v1.0.1
github.com/wailsapp/wails/v2 v2.3.2-0.20230117193915-45c3a501d9e6
golang.org/x/sys v0.7.0
golang.org/x/sys v0.8.0
modernc.org/sqlite v1.21.0
)
@@ -31,6 +32,7 @@ require (
github.com/fatih/color v1.13.0 // indirect
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect
github.com/gookit/color v1.5.2 // indirect
github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e // indirect
github.com/joho/godotenv v1.4.0 // indirect
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
github.com/leaanthony/slicer v1.5.0 // indirect
+7 -2
View File
@@ -41,6 +41,8 @@ github.com/gookit/color v1.5.2 h1:uLnfXcaFjlrDnQDT+NCBcfhrXqYTx/rcCa6xn01Y8yI=
github.com/gookit/color v1.5.2/go.mod h1:w8h4bGiHeeBpvQVePTutdbERIUf3oJE5lZ8HM0UgXyg=
github.com/jackmordaunt/icns/v2 v2.2.1 h1:MGklwYP2yohKn2Bw7XxlF69LZe98S1vUfl5OvAulPwg=
github.com/jackmordaunt/icns/v2 v2.2.1/go.mod h1:6aYIB9eSzyfHHMKqDf17Xrs1zetQPReAkiUSHzdw4cI=
github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e h1:Q3+PugElBCf4PFpxhErSzU3/PY5sFL5Z6rfv4AbGAck=
github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e/go.mod h1:alcuEEnZsY1WQsagKhZDsoPCRoOijYqhZvPwLG0kzVs=
github.com/joho/godotenv v1.4.0 h1:3l4+N6zfMWnkbPEXKng2o2/MR5mSwTrBih4ZEkkz1lg=
github.com/joho/godotenv v1.4.0/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
@@ -140,6 +142,8 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
github.com/tc-hib/winres v0.1.6 h1:qgsYHze+BxQPEYilxIz/KCQGaClvI2+yLBAZs+3+0B8=
github.com/tc-hib/winres v0.1.6/go.mod h1:pe6dOR40VOrGz8PkzreVKNvEKnlE8t4yR8A8naL+t7A=
github.com/wailsapp/go-webview2 v1.0.1 h1:dEJIeEApW/MhO2tTMISZBFZPuW7kwrFA1NtgFB1z1II=
github.com/wailsapp/go-webview2 v1.0.1/go.mod h1:Uk2BePfCRzttBBjFrBmqKGJd41P6QIHeV9kTgIeOZNo=
github.com/wailsapp/mimetype v1.4.1 h1:pQN9ycO7uo4vsUUuPeHEYoUkLVkaRntMnHJxVwYhwHs=
github.com/wailsapp/mimetype v1.4.1/go.mod h1:9aV5k31bBOv5z6u+QP8TltzvNGJPmNJD4XlAL3U+j3o=
github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 h1:QldyIu/L63oPpyvQmHgvgickp1Yw510KJOqX7H24mg8=
@@ -172,6 +176,7 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200810151505-1b9f1253b3ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -185,8 +190,8 @@ golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU=
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
+12 -1
View File
@@ -23,6 +23,9 @@ import (
var globalApplication *App
// isDebugMode is true if the application is running in debug mode
var isDebugMode func() bool
func init() {
runtime.LockOSThread()
}
@@ -53,6 +56,13 @@ func New(appOptions Options) *App {
result.log.AddOutput(&logger.Console{})
}
// Patch isDebug if we aren't in prod mode
if isDebugMode == nil {
isDebugMode = func() bool {
return true
}
}
result.Events = NewWailsEventProcessor(result.dispatchEventToWindows)
opts := assetserveroptions.Options{
@@ -206,7 +216,8 @@ type App struct {
contextMenus map[string]*Menu
contextMenusLock sync.Mutex
assets *assetserver.AssetServer
assets *assetserver.AssetServer
startURL string
// Hooks
windowCreatedCallbacks []func(window *WebviewWindow)
@@ -0,0 +1,10 @@
//go:build production
package application
// We use this to patch the application to production mode.
func init() {
isDebugMode = func() bool {
return false
}
}
@@ -36,7 +36,9 @@ type WebviewWindowOptions struct {
Hidden bool
EnableFraudulentWebsiteWarnings bool
Zoom float64
ZoomControlEnabled bool
EnableDragAndDrop bool
OpenInspectorOnStartup bool
Mac MacWindow
Windows WindowsWindow
Focused bool
+10
View File
@@ -38,6 +38,16 @@ type WindowsWindow struct {
// WindowMask is used to set the window shape. Use a PNG with an alpha channel to create a custom shape.
WindowMask []byte
WindowMaskDraggable bool
// Path where the WebView2 stores the user data. If empty %APPDATA%\[BinaryName.exe] will be used.
// If the path is not valid, a messagebox will be displayed with the error and the app will exit with error code.
WebviewUserDataPath string
// Path to the directory with WebView2 executables. If empty WebView2 installed in the system will be used.
WebviewBrowserPath string
// WebviewGpuIsDisabled is used to enable / disable GPU acceleration for the webview
WebviewGpuIsDisabled bool
}
type Theme int
+3 -1
View File
@@ -1111,7 +1111,9 @@ func (w *macosWebviewWindow) run() {
w.setMaxSize(w.parent.options.MaxWidth, w.parent.options.MaxHeight)
}
//w.setZoom(w.parent.options.Zoom)
w.enableDevTools()
if isDebugMode() {
w.enableDevTools()
}
w.setBackgroundColour(w.parent.options.BackgroundColour)
macOptions := w.parent.options.Mac
+320 -3
View File
@@ -5,12 +5,19 @@ package application
import (
"errors"
"fmt"
"github.com/wailsapp/wails/v2/pkg/assetserver"
"io"
"net/http"
"net/http/httptest"
"net/url"
"strconv"
"strings"
"unicode/utf16"
"unsafe"
"github.com/samber/lo"
"github.com/wailsapp/go-webview2/pkg/edge"
"github.com/wailsapp/wails/v3/pkg/events"
"github.com/wailsapp/wails/v3/pkg/w32"
)
@@ -27,6 +34,10 @@ type windowsWebviewWindow struct {
previousWindowStyle uint32
previousWindowExStyle uint32
previousWindowPlacement w32.WINDOWPLACEMENT
// Webview
chromium *edge.Chromium
hasStarted bool
}
func (w *windowsWebviewWindow) nativeWindowHandle() uintptr {
@@ -89,6 +100,8 @@ func (w *windowsWebviewWindow) run() {
options := w.parent.options
w.chromium = edge.NewChromium()
var exStyle uint
exStyle = w32.WS_EX_CONTROLPARENT | w32.WS_EX_APPWINDOW
if options.BackgroundType != BackgroundTypeSolid {
@@ -197,6 +210,8 @@ func (w *windowsWebviewWindow) run() {
w.Focus()
}
w.setupChromium()
if !options.Hidden {
w.show()
w.update()
@@ -622,6 +637,10 @@ func (w *windowsWebviewWindow) WndProc(msg uint32, wparam, lparam uintptr) uintp
// Unregister the window with the application
windowsApp := globalApplication.impl.(*windowsApp)
windowsApp.unregisterWindow(w)
case w32.WM_NCLBUTTONDOWN:
w32.SetFocus(w.hwnd)
case w32.WM_MOVE, w32.WM_MOVING:
_ = w.chromium.NotifyParentWindowPositionChanged()
case w32.WM_GETMINMAXINFO:
mmi := (*w32.MINMAXINFO)(unsafe.Pointer(lparam))
hasConstraints := false
@@ -742,7 +761,7 @@ func (w *windowsWebviewWindow) WndProc(msg uint32, wparam, lparam uintptr) uintp
// In Full-Screen mode we don't need to adjust anything
// It essential we have the flag here, that is set before SetWindowPos in fullscreen/unfullscreen
// because the native size might not yet reflect we are in fullscreen during this event!
// TODO: w.chromium.SetPadding(edge.Rect{})
w.chromium.SetPadding(edge.Rect{})
} else if w.isMaximised() {
// If the window is maximized we must adjust the client area to the work area of the monitor. Otherwise
// some content goes beyond the visible part of the monitor.
@@ -773,7 +792,7 @@ func (w *windowsWebviewWindow) WndProc(msg uint32, wparam, lparam uintptr) uintp
}
}
}
// TODO: w.chromium.SetPadding(edge.Rect{})
w.chromium.SetPadding(edge.Rect{})
} else {
// This is needed to workaround the resize flickering in frameless mode with WindowDecorations
// See: https://stackoverflow.com/a/6558508
@@ -782,7 +801,7 @@ func (w *windowsWebviewWindow) WndProc(msg uint32, wparam, lparam uintptr) uintp
// Increasing the bottom also worksaround the flickering but we would loose 1px of the WebView content
// therefore let's pad the content with 1px at the bottom.
rgrc.Bottom += 1
// TODO: w.chromium.SetPadding(edge.Rect{Bottom: 1})
w.chromium.SetPadding(edge.Rect{Bottom: 1})
}
return 0
}
@@ -878,6 +897,304 @@ func (w *windowsWebviewWindow) isAlwaysOnTop() bool {
return w32.GetWindowLong(w.hwnd, w32.GWL_EXSTYLE)&w32.WS_EX_TOPMOST != 0
}
// processMessage is given a message sent from JS via the postMessage API
// We put it on the global window message buffer to be processed centrally
func (w *windowsWebviewWindow) processMessage(message string) {
// We send all messages to the centralised window message buffer
windowMessageBuffer <- &windowMessage{
windowId: w.parent.id,
message: message,
}
}
func coreWebview2RequestToHttpRequest(coreReq *edge.ICoreWebView2WebResourceRequest) func() (*http.Request, error) {
return func() (r *http.Request, err error) {
header := http.Header{}
headers, err := coreReq.GetHeaders()
if err != nil {
return nil, fmt.Errorf("GetHeaders Error: %s", err)
}
defer headers.Release()
headersIt, err := headers.GetIterator()
if err != nil {
return nil, fmt.Errorf("GetIterator Error: %s", err)
}
defer headersIt.Release()
for {
has, err := headersIt.HasCurrentHeader()
if err != nil {
return nil, fmt.Errorf("HasCurrentHeader Error: %s", err)
}
if !has {
break
}
name, value, err := headersIt.GetCurrentHeader()
if err != nil {
return nil, fmt.Errorf("GetCurrentHeader Error: %s", err)
}
header.Set(name, value)
if _, err := headersIt.MoveNext(); err != nil {
return nil, fmt.Errorf("MoveNext Error: %s", err)
}
}
method, err := coreReq.GetMethod()
if err != nil {
return nil, fmt.Errorf("GetMethod Error: %s", err)
}
uri, err := coreReq.GetUri()
if err != nil {
return nil, fmt.Errorf("GetUri Error: %s", err)
}
var body io.ReadCloser
if content, err := coreReq.GetContent(); err != nil {
return nil, fmt.Errorf("GetContent Error: %s", err)
} else if content != nil {
body = &iStreamReleaseCloser{stream: content}
}
req, err := http.NewRequest(method, uri, body)
if err != nil {
if body != nil {
body.Close()
}
return nil, err
}
req.Header = header
return req, nil
}
}
type iStreamReleaseCloser struct {
stream *edge.IStream
closed bool
}
func (i *iStreamReleaseCloser) Read(p []byte) (int, error) {
if i.closed {
return 0, io.ErrClosedPipe
}
return i.stream.Read(p)
}
func (i *iStreamReleaseCloser) Close() error {
if i.closed {
return nil
}
i.closed = true
return i.stream.Release()
}
func (w *windowsWebviewWindow) processRequest(req *edge.ICoreWebView2WebResourceRequest, args *edge.ICoreWebView2WebResourceRequestedEventArgs) {
/*
webviewRequests <- &webViewAssetRequest{
Request: webview.NewRequest(wkUrlSchemeTask),
windowId: uint(windowID),
windowName: globalApplication.getWindowForID(uint(windowID)).Name(),
}
*/
// Setting the UserAgent on the CoreWebView2Settings clears the whole default UserAgent of the Edge browser, but
// we want to just append our ApplicationIdentifier. So we adjust the UserAgent for every request.
if reqHeaders, err := req.GetHeaders(); err == nil {
useragent, _ := reqHeaders.GetHeader(assetserver.HeaderUserAgent)
useragent = strings.Join([]string{useragent, assetserver.WailsUserAgentValue}, " ")
reqHeaders.SetHeader(assetserver.HeaderUserAgent, useragent)
reqHeaders.Release()
}
if globalApplication.assets == nil {
// We are using the devServer let the WebView2 handle the request with its default handler
return
}
//Get the request
uri, _ := req.GetUri()
reqUri, err := url.ParseRequestURI(uri)
if err != nil {
globalApplication.error("Unable to parse request uri %s: %s", uri, err)
return
}
if reqUri.Scheme != "http" {
// Let the WebView2 handle the request with its default handler
return
} else if reqUri.Host != "wails.localhost" {
// Let the WebView2 handle the request with its default handler
return
}
rw := httptest.NewRecorder()
globalApplication.assets.ProcessHTTPRequestLegacy(rw, coreWebview2RequestToHttpRequest(req))
headers := []string{}
for k, v := range rw.Header() {
headers = append(headers, fmt.Sprintf("%s: %s", k, strings.Join(v, ",")))
}
env := w.chromium.Environment()
response, err := env.CreateWebResourceResponse(rw.Body.Bytes(), rw.Code, http.StatusText(rw.Code), strings.Join(headers, "\n"))
if err != nil {
globalApplication.error("CreateWebResourceResponse Error: %s", err)
return
}
defer response.Release()
// Send response back
err = args.PutResponse(response)
if err != nil {
globalApplication.error("PutResponse Error: %s", err)
return
}
}
func (w *windowsWebviewWindow) setupChromium() {
chromium := w.chromium
debugMode := isDebugMode()
disableFeatues := []string{}
if !w.parent.options.EnableFraudulentWebsiteWarnings {
disableFeatues = append(disableFeatues, "msSmartScreenProtection")
}
opts := w.parent.options.Windows
chromium.DataPath = opts.WebviewUserDataPath
chromium.BrowserPath = opts.WebviewBrowserPath
if opts.WebviewGpuIsDisabled {
chromium.AdditionalBrowserArgs = append(chromium.AdditionalBrowserArgs, "--disable-gpu")
}
if len(disableFeatues) > 0 {
arg := fmt.Sprintf("--disable-features=%s", strings.Join(disableFeatues, ","))
chromium.AdditionalBrowserArgs = append(chromium.AdditionalBrowserArgs, arg)
}
chromium.MessageCallback = w.processMessage
chromium.WebResourceRequestedCallback = w.processRequest
chromium.NavigationCompletedCallback = w.navigationCompleted
chromium.AcceleratorKeyCallback = func(vkey uint) bool {
w32.PostMessage(w.hwnd, w32.WM_KEYDOWN, uintptr(vkey), 0)
return false
}
chromium.Embed(w.hwnd)
chromium.Resize()
settings, err := chromium.GetSettings()
if err != nil {
globalApplication.fatal(err.Error())
}
err = settings.PutAreDefaultContextMenusEnabled(debugMode)
if err != nil {
globalApplication.fatal(err.Error())
}
err = settings.PutAreDevToolsEnabled(debugMode)
if err != nil {
globalApplication.fatal(err.Error())
}
if w.parent.options.Zoom > 0.0 {
chromium.PutZoomFactor(w.parent.options.Zoom)
}
err = settings.PutIsZoomControlEnabled(w.parent.options.ZoomControlEnabled)
if err != nil {
globalApplication.fatal(err.Error())
}
err = settings.PutIsStatusBarEnabled(false)
if err != nil {
globalApplication.fatal(err.Error())
}
err = settings.PutAreBrowserAcceleratorKeysEnabled(false)
if err != nil {
globalApplication.fatal(err.Error())
}
err = settings.PutIsSwipeNavigationEnabled(false)
if err != nil {
globalApplication.fatal(err.Error())
}
if debugMode && w.parent.options.OpenInspectorOnStartup {
chromium.OpenDevToolsWindow()
}
//TODO: Setup focus event handler
//onFocus := f.mainWindow.OnSetFocus()
//onFocus.Bind(f.onFocus)
// Set background colour
w.setBackgroundColour(w.parent.options.BackgroundColour)
chromium.SetGlobalPermission(edge.CoreWebView2PermissionStateAllow)
chromium.AddWebResourceRequestedFilter("*", edge.COREWEBVIEW2_WEB_RESOURCE_CONTEXT_ALL)
chromium.Navigate("http://wails.localhost")
}
func (w *windowsWebviewWindow) navigationCompleted(sender *edge.ICoreWebView2, args *edge.ICoreWebView2NavigationCompletedEventArgs) {
// TODO: DomReady Event
// Todo: Resize hacks
/*
if f.frontendOptions.Frameless && f.frontendOptions.DisableResize == false {
f.ExecJS("window.wails.flags.enableResize = true;")
}
*/
// TODO: Work out why we need this
//if w.hasStarted {
// return
//}
//w.hasStarted = true
// Hack to make it visible: https://github.com/MicrosoftEdge/WebView2Feedback/issues/1077#issuecomment-825375026
err := w.chromium.Hide()
if err != nil {
globalApplication.fatal(err.Error())
}
if w.parent.options.Hidden {
return
}
err = w.chromium.Show()
if err != nil {
globalApplication.fatal(err.Error())
}
//if w.parent.options.Hidden {
// return
//}
//switch f.frontendOptions.WindowStartState {
//case options.Maximised:
// if !f.frontendOptions.DisableResize {
// win32.ShowWindowMaximised(f.mainWindow.Handle())
// } else {
// win32.ShowWindow(f.mainWindow.Handle())
// }
//case options.Minimised:
// win32.ShowWindowMinimised(f.mainWindow.Handle())
//case options.Fullscreen:
// f.mainWindow.Fullscreen()
// win32.ShowWindow(f.mainWindow.Handle())
//default:
// if f.frontendOptions.Fullscreen {
// f.mainWindow.Fullscreen()
// }
// win32.ShowWindow(f.mainWindow.Handle())
//}
//
//f.mainWindow.hasBeenShown = true
}
func ScaleWithDPI(pixels int, dpi uint) int {
return (pixels * int(dpi)) / 96
}