mirror of
https://github.com/wailsapp/wails.git
synced 2025-05-03 14:29:50 +08:00

* feat: attempt to support Zorin * chore: bump version * Add support for Gentoo * docs: update contributors * feat: test support for Fedora * chore: version bump * Update README.md * feat: major refactor * fix: config errors * fix: capitalisation and binding fix * fix: lint * fix: linting * config: eslint * fix: more lint fixes * fix: linting for hound * Even more fixes * chore: bump version * fix: eslintrc config * fix: renamed global logger * fix: Print stdout on error :rolleyes: * fix: add promises polyfill for the windows target * style: replace double quotes with single quotes * Update contributors * feat: significant overhaul of runtime * chore: Version Bump * Fix Masterminds/semver reference import path (case-sensitivity) * drop lsb_release Signed-off-by: Chronophylos <nikolai@chronophylos.com> * change DistributionID to NAME= Signed-off-by: Chronophylos <nikolai@chronophylos.com> * show distro id when creating a issue Signed-off-by: Chronophylos <nikolai@chronophylos.com> * fix assumption Signed-off-by: Chronophylos <nikolai@chronophylos.com> * docs: updated contributors * fix: add support back for ubuntu, redhat * chore: version bump * fix(linux): fedora & centos support * feat: gcc,npm,node versions on issues * linux working * darwin working * feat: show gcc, node, npm version on issue report * Delete npm-debug.log * fix: crashing typo * trim gcc string * chore: version bump * fix: gitbash fixes * chore: hotfix * fix: issue report * fix: typo * chore: hotfix version bump * 179 parrot distributionsupport (#181) * feat: parrot support && git push * feat: parrot support * feat: parrot support * fix: arch support * fix: gentoos support * Update README.md * Update README.md * chore: bump version * Linux db (#182) * feat: refactor linux distro detection * linux db updates * feat: add gccversioncommand + windows support * fix: build-essential * chore: linter fixes (#185) * 182 linux bd (#183) * fix: linuxdb.yaml entries * fix: typo * fix: yaml syntax error * 188 support distribution linux mint (#189) * chore: update linux db * chore: bump version * chore: merge webview back in * chore: rename webview for clarity * chore: add stale issue bot config * chore: add inprogress label * Azure Pipelines (#192) * test: azure pipeline * test: azure pipeline * test: azure pipeline * test: azure pipeline * test: azure pipeline * test: azure pipeline * test: azure pipeline * test: azure pipeline * test: azure pipeline * test: azure pipeline * test: azure pipeline * test: azure pipeline * test: azure pipeline * test: azure pipeline * test: azure pipeline * test: azure pipeline * test: azure pipeline * test: azure pipeline * test: azure pipeline * test: azure pipeline * test: azure pipeline * test: azure pipeline * test: azure pipeline * test: azure pipeline * test: azure pipeline * test: azure pipeline * test: azure pipeline * test: azure pipeline * test: azure pipeline * test: azure pipeline * test: azure pipeline * test: azure pipeline * test: azure pipeline * test: azure pipeline * feat: azure pipelines * feat: azure pipelines * feat: azure pipelines * feat: azure pipelines * feat: azure pipelines * feat: azure pipelines * feat: azure pipelines * feat: azure pipelines * feat: azure pipelines * feat: azure pipelines * feat: azure pipelines * feat: azure pipelines * feat: azure pipelines * feat: azure pipelines * feat: azure pipelines * feat: azure pipelines * feat: azure pipelines * feat: azure pipelines * feat: azure pipelines * feat: azure pipelines * feat: azure pipelines * feat: azure pipelines * feat: azure pipelines * feat: azure pipelines * feat: azure pipelines * feat: azure pipelines * feat: azure pipelines * feat: azure pipelines * feat: azure pipelines * chore: remove unused mewn file * chore: deduplicate library verificaation code * Update contributors * fix: undefined: webview during build * feat: VoidLinux support * Yaml bug (#207) * test: azure pipeline * fix: azure pipeline yaml * feat: elementary support * feat: opensuse support * fix: 0_setup.go line 27 * fix: 0_setup.go line 27 * fix: opensuse yaml * fix: opensuse yaml * fix: opensuse yaml * fix: opensuse yaml * fix: opensuse yaml * fix: opensuse yaml * fix: yaml * fix: yaml * fix: yaml * fix: opensuse yaml * fix: opensuse * fix: opensuse * fix: opensuse * fix: opensuse * fix: string trim os osRelease field NAME * fix: 0_setup.go if err typo * test * test * fix: typo in linux.go * test: remove quotes from opensuse case * test: revert * test: "" * test: "" * test: "" * test: "" * fix: replace trim with replace * fix: drop 0_setup.go and run checks by system.go * fix: elementary os yaml name * fix: open suse yaml entry * fix: commented out result.Release = version * fix: commented out result.Release = version * fix: revert Replace to Trim * fix: Linux Mint yaml entry * fix: capitalize distros entries * fix: capitalize distros entries * fix: capitalize distros entries * test * test * fix: open suse yaml entry * fix: yaml entris * test * test * test * test * test * test * branch changing * fix: bug in setup process * debugging * debugging * debugging * debugging * fix: yaml entries & err == nil bug * Update prerequisites.go * fix: bug * fix: 0_setup.go * fix: yaml bug * fix: yaml bug * chore: bump version * Elementary support + readme update (#210) * test: azure pipeline * fix: azure pipeline yaml * feat: elementary support+readme udpate * fix: upgrade eslint * 215 support distribution kali (#219) * test: azure pipeline * fix: azure pipeline yaml * feat: kali linux support * feat: kali linux support * fix: allow 0 return types * duplicate code spotted (#221) * fix: duplicate code * chore: release v0.17.14-pre * chore: remove debug output * (FIX) 215 support distribution kali (#224) * fix: kali support * docs: add Mattn * feat: KDE neon support (#234) * chore: version bump * chore: remove some debug output * fix: binding more than one struct method (#245) * feat: add runtime typings * fix: multiple runtime fixes * manjaro (#248) * manjaro * Update go.mod * chore: version bump * fix: update runtime * chore: version bump * cmd/wails: report error status code to OS (#252) Fixes #251. * Update CONTRIBUTORS.md * chore: version bump * fix: importing runtime (#254) * chore: supress warnings * Patch for file dialog on OSX (#258) * Patch for file dialog on OSX * Update CONTRIBUTORS.md * 262 add wails shutdown method (#264) * feat: support close in bridge mode * feat: WailsShutdown callback Now handles proper shutdown through: * runtime.Window.Close() * Killing the main window * Ctrl-C * chore: version bump * fix: force install when node_modules missing (#268) * fix: detect encoding on windows (#266) * fix: linting * chore: bump version * Migrate tool (#270) Experimental migration tool for projects < v1.0.0 * chore: version bump * fix: add flag to fix windows builds (#272) * Bump version to v0.18.9-pre * 261 korean fonts (#273) * fix: linting * chore: bump version * fix: unicode text for Windows * release v0.18.10-pre * 274 support spaces in windows paths (#275) * fix: escape windows commands * fix: allow spaces in path to windres * Update go.mod * release v0.18.11-pre * 261 korean fonts (#276) * fix: linting * chore: bump version * fix: unicode text for Windows * fix: re-add webview_set_title * release v0.18.12-pre * hotfix: build issue for windows * fix: npm/node version reporting * fix: debug build should use terminal * fix: make binary name more os specific * Backport (#283) * Develop (#265) * Patch for file dialog on OSX * Update CONTRIBUTORS.md * 262 add wails shutdown method (#264) * feat: support close in bridge mode * feat: WailsShutdown callback Now handles proper shutdown through: * runtime.Window.Close() * Killing the main window * Ctrl-C * chore: version bump * chore: version bump * feat: adjust binary name for OS * fix: allow spaces in gcc path * feat: migrate command * fix: npm/node versions * fix: allow IE for serve * feat: go build script * fix: make runtime ES2015 compliant * fix: remove invoke patch * fix: allow any line endings * chore: remove legacy bridge files * chore: latest assets * v0.18.15-pre * fix: remove unicode flag * chore: bump version * release v0.19.0
372 lines
11 KiB
Go
Executable File
372 lines
11 KiB
Go
Executable File
// Package webview implements Go bindings to https://github.com/zserge/webview C library.
|
|
// It is a modified version of webview.go from that repository
|
|
// Bindings closely repeat the C APIs and include both, a simplified
|
|
// single-function API to just open a full-screen webview window, and a more
|
|
// advanced and featureful set of APIs, including Go-to-JavaScript bindings.
|
|
//
|
|
// The library uses gtk-webkit, Cocoa/Webkit and MSHTML (IE8..11) as a browser
|
|
// engine and supports Linux, MacOS and Windows 7..10 respectively.
|
|
//
|
|
package webview
|
|
|
|
/*
|
|
#cgo linux openbsd freebsd CFLAGS: -DWEBVIEW_GTK=1 -Wno-deprecated-declarations
|
|
#cgo linux openbsd freebsd pkg-config: gtk+-3.0 webkit2gtk-4.0
|
|
|
|
#cgo windows CFLAGS: -DWEBVIEW_WINAPI=1 -std=c99
|
|
#cgo windows LDFLAGS: -lole32 -lcomctl32 -loleaut32 -luuid -lgdi32
|
|
|
|
#cgo darwin CFLAGS: -DWEBVIEW_COCOA=1 -x objective-c
|
|
#cgo darwin LDFLAGS: -framework Cocoa -framework WebKit
|
|
|
|
#include <stdlib.h>
|
|
#include <stdint.h>
|
|
#define WEBVIEW_STATIC
|
|
#define WEBVIEW_IMPLEMENTATION
|
|
#include "webview.h"
|
|
|
|
extern void _webviewExternalInvokeCallback(void *, void *);
|
|
|
|
static inline void CgoWebViewFree(void *w) {
|
|
free((void *)((struct webview *)w)->title);
|
|
free((void *)((struct webview *)w)->url);
|
|
free(w);
|
|
}
|
|
|
|
static inline void *CgoWebViewCreate(int width, int height, char *title, char *url, int resizable, int debug) {
|
|
struct webview *w = (struct webview *) calloc(1, sizeof(*w));
|
|
w->width = width;
|
|
w->height = height;
|
|
w->title = title;
|
|
w->url = url;
|
|
w->resizable = resizable;
|
|
w->debug = debug;
|
|
w->external_invoke_cb = (webview_external_invoke_cb_t) _webviewExternalInvokeCallback;
|
|
if (webview_init(w) != 0) {
|
|
CgoWebViewFree(w);
|
|
return NULL;
|
|
}
|
|
return (void *)w;
|
|
}
|
|
|
|
static inline int CgoWebViewLoop(void *w, int blocking) {
|
|
return webview_loop((struct webview *)w, blocking);
|
|
}
|
|
|
|
static inline void CgoWebViewTerminate(void *w) {
|
|
webview_terminate((struct webview *)w);
|
|
}
|
|
|
|
static inline void CgoWebViewExit(void *w) {
|
|
webview_exit((struct webview *)w);
|
|
}
|
|
|
|
static inline void CgoWebViewSetTitle(void *w, char *title) {
|
|
webview_set_title((struct webview *)w, title);
|
|
}
|
|
|
|
static inline void CgoWebViewSetFullscreen(void *w, int fullscreen) {
|
|
webview_set_fullscreen((struct webview *)w, fullscreen);
|
|
}
|
|
|
|
static inline void CgoWebViewSetColor(void *w, uint8_t r, uint8_t g, uint8_t b, uint8_t a) {
|
|
webview_set_color((struct webview *)w, r, g, b, a);
|
|
}
|
|
|
|
static inline void CgoDialog(void *w, int dlgtype, int flags,
|
|
char *title, char *arg, char *res, size_t ressz) {
|
|
webview_dialog(w, dlgtype, flags,
|
|
(const char*)title, (const char*) arg, res, ressz);
|
|
}
|
|
|
|
static inline int CgoWebViewEval(void *w, char *js) {
|
|
return webview_eval((struct webview *)w, js);
|
|
}
|
|
|
|
static inline void CgoWebViewInjectCSS(void *w, char *css) {
|
|
webview_inject_css((struct webview *)w, css);
|
|
}
|
|
|
|
extern void _webviewDispatchGoCallback(void *);
|
|
static inline void _webview_dispatch_cb(struct webview *w, void *arg) {
|
|
_webviewDispatchGoCallback(arg);
|
|
}
|
|
static inline void CgoWebViewDispatch(void *w, uintptr_t arg) {
|
|
webview_dispatch((struct webview *)w, _webview_dispatch_cb, (void *)arg);
|
|
}
|
|
*/
|
|
import "C"
|
|
import (
|
|
"errors"
|
|
"runtime"
|
|
"sync"
|
|
"unsafe"
|
|
)
|
|
|
|
func init() {
|
|
// Ensure that main.main is called from the main thread
|
|
runtime.LockOSThread()
|
|
}
|
|
|
|
// Open is a simplified API to open a single native window with a full-size webview in
|
|
// it. It can be helpful if you want to communicate with the core app using XHR
|
|
// or WebSockets (as opposed to using JavaScript bindings).
|
|
//
|
|
// Window appearance can be customized using title, width, height and resizable parameters.
|
|
// URL must be provided and can user either a http or https protocol, or be a
|
|
// local file:// URL. On some platforms "data:" URLs are also supported
|
|
// (Linux/MacOS).
|
|
func Open(title, url string, w, h int, resizable bool) error {
|
|
titleStr := C.CString(title)
|
|
defer C.free(unsafe.Pointer(titleStr))
|
|
urlStr := C.CString(url)
|
|
defer C.free(unsafe.Pointer(urlStr))
|
|
resize := C.int(0)
|
|
if resizable {
|
|
resize = C.int(1)
|
|
}
|
|
|
|
r := C.webview(titleStr, urlStr, C.int(w), C.int(h), resize)
|
|
if r != 0 {
|
|
return errors.New("failed to create webview")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// ExternalInvokeCallbackFunc is a function type that is called every time
|
|
// "window.external.invoke()" is called from JavaScript. Data is the only
|
|
// obligatory string parameter passed into the "invoke(data)" function from
|
|
// JavaScript. To pass more complex data serialized JSON or base64 encoded
|
|
// string can be used.
|
|
type ExternalInvokeCallbackFunc func(w WebView, data string)
|
|
|
|
// Settings is a set of parameters to customize the initial WebView appearance
|
|
// and behavior. It is passed into the webview.New() constructor.
|
|
type Settings struct {
|
|
// WebView main window title
|
|
Title string
|
|
// URL to open in a webview
|
|
URL string
|
|
// Window width in pixels
|
|
Width int
|
|
// Window height in pixels
|
|
Height int
|
|
// Allows/disallows window resizing
|
|
Resizable bool
|
|
// Enable debugging tools (Linux/BSD/MacOS, on Windows use Firebug)
|
|
Debug bool
|
|
// A callback that is executed when JavaScript calls "window.external.invoke()"
|
|
ExternalInvokeCallback ExternalInvokeCallbackFunc
|
|
}
|
|
|
|
// WebView is an interface that wraps the basic methods for controlling the UI
|
|
// loop, handling multithreading and providing JavaScript bindings.
|
|
type WebView interface {
|
|
// Run() starts the main UI loop until the user closes the webview window or
|
|
// Terminate() is called.
|
|
Run()
|
|
// Loop() runs a single iteration of the main UI.
|
|
Loop(blocking bool) bool
|
|
// SetTitle() changes window title. This method must be called from the main
|
|
// thread only. See Dispatch() for more details.
|
|
SetTitle(title string)
|
|
// SetFullscreen() controls window full-screen mode. This method must be
|
|
// called from the main thread only. See Dispatch() for more details.
|
|
SetFullscreen(fullscreen bool)
|
|
// SetColor() changes window background color. This method must be called from
|
|
// the main thread only. See Dispatch() for more details.
|
|
SetColor(r, g, b, a uint8)
|
|
// Eval() evaluates an arbitrary JS code inside the webview. This method must
|
|
// be called from the main thread only. See Dispatch() for more details.
|
|
Eval(js string) error
|
|
// InjectJS() injects an arbitrary block of CSS code using the JS API. This
|
|
// method must be called from the main thread only. See Dispatch() for more
|
|
// details.
|
|
InjectCSS(css string)
|
|
// Dialog() opens a system dialog of the given type and title. String
|
|
// argument can be provided for certain dialogs, such as alert boxes. For
|
|
// alert boxes argument is a message inside the dialog box.
|
|
Dialog(dlgType DialogType, flags int, title string, arg string) string
|
|
// Terminate() breaks the main UI loop. This method must be called from the main thread
|
|
// only. See Dispatch() for more details.
|
|
Terminate()
|
|
// Dispatch() schedules some arbitrary function to be executed on the main UI
|
|
// thread. This may be helpful if you want to run some JavaScript from
|
|
// background threads/goroutines, or to terminate the app.
|
|
Dispatch(func())
|
|
// Exit() closes the window and cleans up the resources. Use Terminate() to
|
|
// forcefully break out of the main UI loop.
|
|
Exit()
|
|
}
|
|
|
|
// DialogType is an enumeration of all supported system dialog types
|
|
type DialogType int
|
|
|
|
const (
|
|
// DialogTypeOpen is a system file open dialog
|
|
DialogTypeOpen DialogType = iota
|
|
// DialogTypeSave is a system file save dialog
|
|
DialogTypeSave
|
|
// DialogTypeAlert is a system alert dialog (message box)
|
|
DialogTypeAlert
|
|
)
|
|
|
|
const (
|
|
// DialogFlagFile is a normal file picker dialog
|
|
DialogFlagFile = C.WEBVIEW_DIALOG_FLAG_FILE
|
|
// DialogFlagDirectory is an open directory dialog
|
|
DialogFlagDirectory = C.WEBVIEW_DIALOG_FLAG_DIRECTORY
|
|
// DialogFlagInfo is an info alert dialog
|
|
DialogFlagInfo = C.WEBVIEW_DIALOG_FLAG_INFO
|
|
// DialogFlagWarning is a warning alert dialog
|
|
DialogFlagWarning = C.WEBVIEW_DIALOG_FLAG_WARNING
|
|
// DialogFlagError is an error dialog
|
|
DialogFlagError = C.WEBVIEW_DIALOG_FLAG_ERROR
|
|
)
|
|
|
|
var (
|
|
m sync.Mutex
|
|
index uintptr
|
|
fns = map[uintptr]func(){}
|
|
cbs = map[WebView]ExternalInvokeCallbackFunc{}
|
|
)
|
|
|
|
type webview struct {
|
|
w unsafe.Pointer
|
|
}
|
|
|
|
var _ WebView = &webview{}
|
|
|
|
func boolToInt(b bool) int {
|
|
if b {
|
|
return 1
|
|
}
|
|
return 0
|
|
}
|
|
|
|
// NewWebview creates and opens a new webview window using the given settings. The
|
|
// returned object implements the WebView interface. This function returns nil
|
|
// if a window can not be created.
|
|
func NewWebview(settings Settings) WebView {
|
|
if settings.Width == 0 {
|
|
settings.Width = 640
|
|
}
|
|
if settings.Height == 0 {
|
|
settings.Height = 480
|
|
}
|
|
if settings.Title == "" {
|
|
settings.Title = "WebView"
|
|
}
|
|
w := &webview{}
|
|
w.w = C.CgoWebViewCreate(C.int(settings.Width), C.int(settings.Height),
|
|
C.CString(settings.Title), C.CString(settings.URL),
|
|
C.int(boolToInt(settings.Resizable)), C.int(boolToInt(settings.Debug)))
|
|
m.Lock()
|
|
if settings.ExternalInvokeCallback != nil {
|
|
cbs[w] = settings.ExternalInvokeCallback
|
|
} else {
|
|
cbs[w] = func(w WebView, data string) {}
|
|
}
|
|
m.Unlock()
|
|
return w
|
|
}
|
|
|
|
func (w *webview) Loop(blocking bool) bool {
|
|
block := C.int(0)
|
|
if blocking {
|
|
block = 1
|
|
}
|
|
return C.CgoWebViewLoop(w.w, block) == 0
|
|
}
|
|
|
|
func (w *webview) Run() {
|
|
for w.Loop(true) {
|
|
}
|
|
}
|
|
|
|
func (w *webview) Exit() {
|
|
C.CgoWebViewExit(w.w)
|
|
}
|
|
|
|
func (w *webview) Dispatch(f func()) {
|
|
m.Lock()
|
|
for ; fns[index] != nil; index++ {
|
|
}
|
|
fns[index] = f
|
|
m.Unlock()
|
|
C.CgoWebViewDispatch(w.w, C.uintptr_t(index))
|
|
}
|
|
|
|
func (w *webview) SetTitle(title string) {
|
|
p := C.CString(title)
|
|
defer C.free(unsafe.Pointer(p))
|
|
C.CgoWebViewSetTitle(w.w, p)
|
|
}
|
|
|
|
func (w *webview) SetColor(r, g, b, a uint8) {
|
|
C.CgoWebViewSetColor(w.w, C.uint8_t(r), C.uint8_t(g), C.uint8_t(b), C.uint8_t(a))
|
|
}
|
|
|
|
func (w *webview) SetFullscreen(fullscreen bool) {
|
|
C.CgoWebViewSetFullscreen(w.w, C.int(boolToInt(fullscreen)))
|
|
}
|
|
|
|
func (w *webview) Dialog(dlgType DialogType, flags int, title string, arg string) string {
|
|
const maxPath = 4096
|
|
titlePtr := C.CString(title)
|
|
defer C.free(unsafe.Pointer(titlePtr))
|
|
argPtr := C.CString(arg)
|
|
defer C.free(unsafe.Pointer(argPtr))
|
|
resultPtr := (*C.char)(C.calloc((C.size_t)(unsafe.Sizeof((*C.char)(nil))), (C.size_t)(maxPath)))
|
|
defer C.free(unsafe.Pointer(resultPtr))
|
|
C.CgoDialog(w.w, C.int(dlgType), C.int(flags), titlePtr,
|
|
argPtr, resultPtr, C.size_t(maxPath))
|
|
return C.GoString(resultPtr)
|
|
}
|
|
|
|
func (w *webview) Eval(js string) error {
|
|
p := C.CString(js)
|
|
defer C.free(unsafe.Pointer(p))
|
|
switch C.CgoWebViewEval(w.w, p) {
|
|
case -1:
|
|
return errors.New("evaluation failed")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (w *webview) InjectCSS(css string) {
|
|
p := C.CString(css)
|
|
defer C.free(unsafe.Pointer(p))
|
|
C.CgoWebViewInjectCSS(w.w, p)
|
|
}
|
|
|
|
func (w *webview) Terminate() {
|
|
C.CgoWebViewTerminate(w.w)
|
|
}
|
|
|
|
//export _webviewDispatchGoCallback
|
|
func _webviewDispatchGoCallback(index unsafe.Pointer) {
|
|
var f func()
|
|
m.Lock()
|
|
f = fns[uintptr(index)]
|
|
delete(fns, uintptr(index))
|
|
m.Unlock()
|
|
f()
|
|
}
|
|
|
|
//export _webviewExternalInvokeCallback
|
|
func _webviewExternalInvokeCallback(w unsafe.Pointer, data unsafe.Pointer) {
|
|
m.Lock()
|
|
var (
|
|
cb ExternalInvokeCallbackFunc
|
|
wv WebView
|
|
)
|
|
for wv, cb = range cbs {
|
|
if wv.(*webview).w == w {
|
|
break
|
|
}
|
|
}
|
|
m.Unlock()
|
|
cb(wv, C.GoString((*C.char)(data)))
|
|
}
|