mirror of
https://github.com/wavetermdev/wails.git
synced 2026-04-22 15:26:15 -07:00
Compare commits
41 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 37b395c308 | |||
| 428584d583 | |||
| ee1978aa42 | |||
| 895d6d4b80 | |||
| a5ddce2c7c | |||
| e4789750c8 | |||
| f8c673874b | |||
| 5ef32760f0 | |||
| 81645190f0 | |||
| 18d0ed890a | |||
| 2479603143 | |||
| dbf6b3a718 | |||
| 45c3a501d9 | |||
| 401165ce30 | |||
| caa0b6c804 | |||
| 8f92cf1074 | |||
| 8c7fa4cf4c | |||
| d0bd849be6 | |||
| 0a98efeea9 | |||
| 93cfc777f9 | |||
| d15e673a19 | |||
| ec8e9b2715 | |||
| aaf039bcff | |||
| 05679e70d0 | |||
| 8e4606d104 | |||
| 54ca6c7059 | |||
| 6e3b4cf1a1 | |||
| c3011813b0 | |||
| ccceadbd24 | |||
| e1fc7119bc | |||
| add10df5ff | |||
| 284e20a290 | |||
| 0a32c1124e | |||
| fc9dd99dea | |||
| 2727af43d4 | |||
| 4d0163d8af | |||
| ebc653a584 | |||
| ef5f547d27 | |||
| d3b4105f75 | |||
| 66bc258f81 | |||
| 908aecfd1c |
@@ -31,3 +31,6 @@ v2/test/kitchensink/frontend/package.json.md5
|
||||
v2/cmd/wails/internal/commands/initialise/templates/testtemplates/
|
||||
.env
|
||||
/website/static/img/.cache.json
|
||||
|
||||
/v3/.task
|
||||
/v3/examples/build/bin/testapp
|
||||
|
||||
+2
-2
@@ -30,8 +30,8 @@
|
||||
<img alt="Slack" src="https://img.shields.io/badge/slack-gophers%2Fwails%20-blue?logo=slack"/>
|
||||
</a>
|
||||
<br/>
|
||||
<a href="https://github.com/wailsapp/wails/actions/workflows/build.yml" rel="nofollow">
|
||||
<img src="https://img.shields.io/github/workflow/status/wailsapp/wails/Build?logo=github" alt="Build" />
|
||||
<a href="https://github.com/wailsapp/wails/actions/workflows/build-and-test.yml" rel="nofollow">
|
||||
<img src="https://img.shields.io/github/actions/workflow/status/wailsapp/wails/build-and-test.yml?branch=master&logo=Github" alt="Build" />
|
||||
</a>
|
||||
<a href="https://github.com/wailsapp/wails/tags" rel="nofollow">
|
||||
<img alt="GitHub tag (latest SemVer pre-release)" src="https://img.shields.io/github/v/tag/wailsapp/wails?include_prereleases&label=version"/>
|
||||
|
||||
+2
-2
@@ -30,8 +30,8 @@
|
||||
<img alt="Slack" src="https://img.shields.io/badge/slack-gophers%2Fwails%20-blue?logo=slack"/>
|
||||
</a>
|
||||
<br/>
|
||||
<a href="https://github.com/wailsapp/wails/actions/workflows/build.yml" rel="nofollow">
|
||||
<img src="https://img.shields.io/github/workflow/status/wailsapp/wails/Build?logo=github" alt="Build" />
|
||||
<a href="https://github.com/wailsapp/wails/actions/workflows/build-and-test.yml" rel="nofollow">
|
||||
<img src="https://img.shields.io/github/actions/workflow/status/wailsapp/wails/build-and-test.yml?branch=master&logo=Github" alt="Build" />
|
||||
</a>
|
||||
<a href="https://github.com/wailsapp/wails/tags" rel="nofollow">
|
||||
<img alt="GitHub tag (latest SemVer pre-release)" src="https://img.shields.io/github/v/tag/wailsapp/wails?include_prereleases&label=version"/>
|
||||
|
||||
@@ -28,8 +28,8 @@
|
||||
<img alt="Slack" src="https://img.shields.io/badge/slack-gophers%2Fwails%20-blue?logo=slack"/>
|
||||
</a>
|
||||
<br/>
|
||||
<a href="https://github.com/wailsapp/wails/actions/workflows/build.yml" rel="nofollow">
|
||||
<img src="https://img.shields.io/github/workflow/status/wailsapp/wails/Build?logo=github" alt="Build" />
|
||||
<a href="https://github.com/wailsapp/wails/actions/workflows/build-and-test.yml" rel="nofollow">
|
||||
<img src="https://img.shields.io/github/actions/workflow/status/wailsapp/wails/build-and-test.yml?branch=master&logo=Github" alt="Build" />
|
||||
</a>
|
||||
<a href="https://github.com/wailsapp/wails/tags" rel="nofollow">
|
||||
<img alt="GitHub tag (latest SemVer pre-release)" src="https://img.shields.io/github/v/tag/wailsapp/wails?include_prereleases&label=version"/>
|
||||
|
||||
+2
-2
@@ -30,8 +30,8 @@
|
||||
<img alt="Slack" src="https://img.shields.io/badge/slack-gophers%2Fwails%20-blue?logo=slack"/>
|
||||
</a>
|
||||
<br/>
|
||||
<a href="https://github.com/wailsapp/wails/actions/workflows/build.yml" rel="nofollow">
|
||||
<img src="https://img.shields.io/github/workflow/status/wailsapp/wails/Build?logo=github" alt="Build" />
|
||||
<a href="https://github.com/wailsapp/wails/actions/workflows/build-and-test.yml" rel="nofollow">
|
||||
<img src="https://img.shields.io/github/actions/workflow/status/wailsapp/wails/build-and-test.yml?branch=master&logo=Github" alt="Build" />
|
||||
</a>
|
||||
<a href="https://github.com/wailsapp/wails/tags" rel="nofollow">
|
||||
<img alt="GitHub tag (latest SemVer pre-release)" src="https://img.shields.io/github/v/tag/wailsapp/wails?include_prereleases&label=version"/>
|
||||
|
||||
@@ -2,14 +2,15 @@ package flags
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/leaanthony/slicer"
|
||||
"github.com/wailsapp/wails/v2/internal/system"
|
||||
"github.com/wailsapp/wails/v2/pkg/commands/build"
|
||||
"github.com/wailsapp/wails/v2/pkg/commands/buildtags"
|
||||
"os"
|
||||
"os/exec"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
"github.com/leaanthony/slicer"
|
||||
"github.com/wailsapp/wails/v2/internal/system"
|
||||
"github.com/wailsapp/wails/v2/pkg/commands/build"
|
||||
"github.com/wailsapp/wails/v2/pkg/commands/buildtags"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -51,7 +52,6 @@ type Build struct {
|
||||
}
|
||||
|
||||
func (b *Build) Default() *Build {
|
||||
|
||||
defaultPlatform := os.Getenv("GOOS")
|
||||
if defaultPlatform == "" {
|
||||
defaultPlatform = runtime.GOOS
|
||||
@@ -64,13 +64,13 @@ func (b *Build) Default() *Build {
|
||||
defaultArch = runtime.GOARCH
|
||||
}
|
||||
}
|
||||
b.defaultArch = defaultArch
|
||||
platform := defaultPlatform + "/" + defaultArch
|
||||
|
||||
result := &Build{
|
||||
Platform: platform,
|
||||
Platform: defaultPlatform + "/" + defaultArch,
|
||||
WebView2: "download",
|
||||
GarbleArgs: "-literals -tiny -seed=random",
|
||||
|
||||
defaultArch: defaultArch,
|
||||
}
|
||||
result.BuildCommon = result.BuildCommon.Default()
|
||||
return result
|
||||
|
||||
@@ -4,12 +4,13 @@ import (
|
||||
"context"
|
||||
"embed"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/wailsapp/wails/v2/pkg/application"
|
||||
"github.com/wailsapp/wails/v2/pkg/menu"
|
||||
"github.com/wailsapp/wails/v2/pkg/options"
|
||||
"github.com/wailsapp/wails/v2/pkg/options/windows"
|
||||
"github.com/wailsapp/wails/v2/pkg/runtime"
|
||||
"time"
|
||||
)
|
||||
|
||||
//go:embed all:frontend/dist
|
||||
|
||||
@@ -12,8 +12,9 @@ import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/wailsapp/wails/v2/pkg/assetserver"
|
||||
|
||||
"github.com/wailsapp/wails/v2/internal/binding"
|
||||
"github.com/wailsapp/wails/v2/internal/frontend/assetserver"
|
||||
"github.com/wailsapp/wails/v2/internal/frontend/desktop"
|
||||
"github.com/wailsapp/wails/v2/internal/frontend/devserver"
|
||||
"github.com/wailsapp/wails/v2/internal/frontend/dispatcher"
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
#define WindowStartsMinimised 2
|
||||
#define WindowStartsFullscreen 3
|
||||
|
||||
WailsContext* Create(const char* title, int width, int height, int frameless, int resizable, int fullscreen, int fullSizeContent, int hideTitleBar, int titlebarAppearsTransparent, int hideTitle, int useToolbar, int hideToolbarSeparator, int webviewIsTransparent, int alwaysOnTop, int hideWindowOnClose, const char *appearance, int windowIsTranslucent, int debug, int windowStartState, int startsHidden, int minWidth, int minHeight, int maxWidth, int maxHeight);
|
||||
WailsContext* Create(const char* title, int width, int height, int frameless, int resizable, int fullscreen, int fullSizeContent, int hideTitleBar, int titlebarAppearsTransparent, int hideTitle, int useToolbar, int hideToolbarSeparator, int webviewIsTransparent, int alwaysOnTop, int hideWindowOnClose, const char *appearance, int windowIsTranslucent, int debug, int windowStartState, int startsHidden, int minWidth, int minHeight, int maxWidth, int maxHeight, bool fraudulentWebsiteWarningEnabled);
|
||||
void Run(void*, const char* url);
|
||||
|
||||
void SetTitle(void* ctx, const char *title);
|
||||
@@ -48,11 +48,6 @@ const bool IsFullScreen(void *ctx);
|
||||
const bool IsMinimised(void *ctx);
|
||||
const bool IsMaximised(void *ctx);
|
||||
|
||||
void ProcessURLDidReceiveResponse(void *inctx, unsigned long long requestId, int statusCode, void *headersString, int headersStringLength);
|
||||
bool ProcessURLDidReceiveData(void *inctx, unsigned long long requestId, void* data, int datalength);
|
||||
void ProcessURLDidFinish(void *inctx, unsigned long long requestId);
|
||||
int ProcessURLRequestReadBodyStream(void *inctx, unsigned long long requestId, void *buf, int bufLen);
|
||||
|
||||
/* Dialogs */
|
||||
|
||||
void MessageDialog(void *inctx, const char* dialogType, const char* title, const char* message, const char* button1, const char* button2, const char* button3, const char* button4, const char* defaultButton, const char* cancelButton, void* iconData, int iconDataLength);
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
#import "WailsMenu.h"
|
||||
#import "WailsMenuItem.h"
|
||||
|
||||
WailsContext* Create(const char* title, int width, int height, int frameless, int resizable, int fullscreen, int fullSizeContent, int hideTitleBar, int titlebarAppearsTransparent, int hideTitle, int useToolbar, int hideToolbarSeparator, int webviewIsTransparent, int alwaysOnTop, int hideWindowOnClose, const char *appearance, int windowIsTranslucent, int debug, int windowStartState, int startsHidden, int minWidth, int minHeight, int maxWidth, int maxHeight) {
|
||||
WailsContext* Create(const char* title, int width, int height, int frameless, int resizable, int fullscreen, int fullSizeContent, int hideTitleBar, int titlebarAppearsTransparent, int hideTitle, int useToolbar, int hideToolbarSeparator, int webviewIsTransparent, int alwaysOnTop, int hideWindowOnClose, const char *appearance, int windowIsTranslucent, int debug, int windowStartState, int startsHidden, int minWidth, int minHeight, int maxWidth, int maxHeight, bool fraudulentWebsiteWarningEnabled) {
|
||||
|
||||
[NSApplication sharedApplication];
|
||||
|
||||
@@ -25,7 +25,7 @@ WailsContext* Create(const char* title, int width, int height, int frameless, in
|
||||
fullscreen = 1;
|
||||
}
|
||||
|
||||
[result CreateWindow:width :height :frameless :resizable :fullscreen :fullSizeContent :hideTitleBar :titlebarAppearsTransparent :hideTitle :useToolbar :hideToolbarSeparator :webviewIsTransparent :hideWindowOnClose :safeInit(appearance) :windowIsTranslucent :minWidth :minHeight :maxWidth :maxHeight];
|
||||
[result CreateWindow:width :height :frameless :resizable :fullscreen :fullSizeContent :hideTitleBar :titlebarAppearsTransparent :hideTitle :useToolbar :hideToolbarSeparator :webviewIsTransparent :hideWindowOnClose :safeInit(appearance) :windowIsTranslucent :minWidth :minHeight :maxWidth :maxHeight :fraudulentWebsiteWarningEnabled];
|
||||
[result SetTitle:safeInit(title)];
|
||||
[result Center];
|
||||
|
||||
@@ -52,36 +52,6 @@ WailsContext* Create(const char* title, int width, int height, int frameless, in
|
||||
return result;
|
||||
}
|
||||
|
||||
void ProcessURLDidReceiveResponse(void *inctx, unsigned long long requestId, int statusCode, void *headersString, int headersStringLength) {
|
||||
WailsContext *ctx = (__bridge WailsContext*) inctx;
|
||||
@autoreleasepool {
|
||||
NSData *nsHeadersJSON = [NSData dataWithBytes:headersString length:headersStringLength];
|
||||
[ctx processURLDidReceiveResponse:requestId :statusCode :nsHeadersJSON];
|
||||
}
|
||||
}
|
||||
|
||||
bool ProcessURLDidReceiveData(void *inctx, unsigned long long requestId, void* data, int datalength) {
|
||||
WailsContext *ctx = (__bridge WailsContext*) inctx;
|
||||
@autoreleasepool {
|
||||
NSData *nsdata = [NSData dataWithBytes:data length:datalength];
|
||||
return [ctx processURLDidReceiveData:requestId :nsdata];
|
||||
}
|
||||
}
|
||||
|
||||
void ProcessURLDidFinish(void *inctx, unsigned long long requestId) {
|
||||
WailsContext *ctx = (__bridge WailsContext*) inctx;
|
||||
@autoreleasepool {
|
||||
[ctx processURLDidFinish:requestId];
|
||||
}
|
||||
}
|
||||
|
||||
int ProcessURLRequestReadBodyStream(void *inctx, unsigned long long requestId, void *buf, int bufLen) {
|
||||
WailsContext *ctx = (__bridge WailsContext*) inctx;
|
||||
@autoreleasepool {
|
||||
return [ctx processURLRequestReadBodyStream:requestId :buf :bufLen];
|
||||
}
|
||||
}
|
||||
|
||||
void ExecJS(void* inctx, const char *script) {
|
||||
WailsContext *ctx = (__bridge WailsContext*) inctx;
|
||||
NSString *nsscript = safeInit(script);
|
||||
|
||||
@@ -47,9 +47,6 @@
|
||||
@property bool debug;
|
||||
|
||||
@property (retain) WKUserContentController* userContentController;
|
||||
@property (retain) NSLock *urlRequestsLock;
|
||||
@property unsigned long long urlRequestsId;
|
||||
@property (retain) NSMutableDictionary *urlRequests;
|
||||
|
||||
@property (retain) NSMenu* applicationMenu;
|
||||
|
||||
@@ -57,7 +54,7 @@
|
||||
@property (retain) NSString* aboutTitle;
|
||||
@property (retain) NSString* aboutDescription;
|
||||
|
||||
- (void) CreateWindow:(int)width :(int)height :(bool)frameless :(bool)resizable :(bool)fullscreen :(bool)fullSizeContent :(bool)hideTitleBar :(bool)titlebarAppearsTransparent :(bool)hideTitle :(bool)useToolbar :(bool)hideToolbarSeparator :(bool)webviewIsTransparent :(bool)hideWindowOnClose :(NSString *)appearance :(bool)windowIsTranslucent :(int)minWidth :(int)minHeight :(int)maxWidth :(int)maxHeight;
|
||||
- (void) CreateWindow:(int)width :(int)height :(bool)frameless :(bool)resizable :(bool)fullscreen :(bool)fullSizeContent :(bool)hideTitleBar :(bool)titlebarAppearsTransparent :(bool)hideTitle :(bool)useToolbar :(bool)hideToolbarSeparator :(bool)webviewIsTransparent :(bool)hideWindowOnClose :(NSString *)appearance :(bool)windowIsTranslucent :(int)minWidth :(int)minHeight :(int)maxWidth :(int)maxHeight :(bool)fraudulentWebsiteWarningEnabled;
|
||||
- (void) SetSize:(int)width :(int)height;
|
||||
- (void) SetPosition:(int)x :(int) y;
|
||||
- (void) SetMinSize:(int)minWidth :(int)minHeight;
|
||||
@@ -89,10 +86,6 @@
|
||||
- (void) SaveFileDialog :(NSString*)title :(NSString*)defaultFilename :(NSString*)defaultDirectory :(bool)canCreateDirectories :(bool)treatPackagesAsDirectories :(bool)showHiddenFiles :(NSString*)filters;
|
||||
|
||||
- (void) loadRequest:(NSString*)url;
|
||||
- (void) processURLDidReceiveResponse:(unsigned long long)requestId :(int)statusCode :(NSData *)headersJSON;
|
||||
- (bool) processURLDidReceiveData:(unsigned long long)requestId :(NSData *)data;
|
||||
- (void) processURLDidFinish:(unsigned long long)requestId;
|
||||
- (int) processURLRequestReadBodyStream:(unsigned long long)requestId :(void *)buf :(int)bufLen;
|
||||
- (void) ExecJS:(NSString*)script;
|
||||
- (NSScreen*) getCurrentScreen;
|
||||
|
||||
|
||||
@@ -108,7 +108,6 @@ typedef void (^schemeTaskCaller)(id<WKURLSchemeTask>);
|
||||
[self.mainWindow release];
|
||||
[self.mouseEvent release];
|
||||
[self.userContentController release];
|
||||
[self.urlRequests release];
|
||||
[self.applicationMenu release];
|
||||
[super dealloc];
|
||||
}
|
||||
@@ -137,10 +136,7 @@ typedef void (^schemeTaskCaller)(id<WKURLSchemeTask>);
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (void) CreateWindow:(int)width :(int)height :(bool)frameless :(bool)resizable :(bool)fullscreen :(bool)fullSizeContent :(bool)hideTitleBar :(bool)titlebarAppearsTransparent :(bool)hideTitle :(bool)useToolbar :(bool)hideToolbarSeparator :(bool)webviewIsTransparent :(bool)hideWindowOnClose :(NSString*)appearance :(bool)windowIsTranslucent :(int)minWidth :(int)minHeight :(int)maxWidth :(int)maxHeight {
|
||||
self.urlRequestsId = 0;
|
||||
self.urlRequests = [NSMutableDictionary new];
|
||||
|
||||
- (void) CreateWindow:(int)width :(int)height :(bool)frameless :(bool)resizable :(bool)fullscreen :(bool)fullSizeContent :(bool)hideTitleBar :(bool)titlebarAppearsTransparent :(bool)hideTitle :(bool)useToolbar :(bool)hideToolbarSeparator :(bool)webviewIsTransparent :(bool)hideWindowOnClose :(NSString*)appearance :(bool)windowIsTranslucent :(int)minWidth :(int)minHeight :(int)maxWidth :(int)maxHeight :(bool)fraudulentWebsiteWarningEnabled {
|
||||
NSWindowStyleMask styleMask = 0;
|
||||
|
||||
if( !frameless ) {
|
||||
@@ -220,7 +216,11 @@ typedef void (^schemeTaskCaller)(id<WKURLSchemeTask>);
|
||||
[config setURLSchemeHandler:self forURLScheme:@"wails"];
|
||||
|
||||
// [config.preferences setValue:[NSNumber numberWithBool:true] forKey:@"developerExtrasEnabled"];
|
||||
|
||||
|
||||
if (@available(macOS 10.15, *)) {
|
||||
config.preferences.fraudulentWebsiteWarningEnabled = fraudulentWebsiteWarningEnabled;
|
||||
}
|
||||
|
||||
WKUserContentController* userContentController = [WKUserContentController new];
|
||||
[userContentController addScriptMessageHandler:self name:@"external"];
|
||||
config.userContentController = userContentController;
|
||||
@@ -427,156 +427,19 @@ typedef void (^schemeTaskCaller)(id<WKURLSchemeTask>);
|
||||
}];
|
||||
}
|
||||
|
||||
- (void) processURLDidReceiveResponse:(unsigned long long)requestId :(int)statusCode :(NSData *)headersJSON {
|
||||
[self processURLSchemeTaskCall:requestId :^(id<WKURLSchemeTask> urlSchemeTask) {
|
||||
NSDictionary *headerFields = [NSJSONSerialization JSONObjectWithData: headersJSON options: NSJSONReadingMutableContainers error: nil];
|
||||
NSHTTPURLResponse *response = [[[NSHTTPURLResponse alloc] initWithURL:urlSchemeTask.request.URL statusCode:statusCode HTTPVersion:@"HTTP/1.1" headerFields:headerFields] autorelease];
|
||||
|
||||
[urlSchemeTask didReceiveResponse:response];
|
||||
}];
|
||||
}
|
||||
|
||||
- (bool) processURLDidReceiveData:(unsigned long long)requestId :(NSData *)data {
|
||||
return [self processURLSchemeTaskCall:requestId :^(id<WKURLSchemeTask> urlSchemeTask) {
|
||||
[urlSchemeTask didReceiveData:data];
|
||||
}];
|
||||
}
|
||||
|
||||
- (void) processURLDidFinish:(unsigned long long)requestId {
|
||||
[self processURLSchemeTaskCall:requestId :^(id<WKURLSchemeTask> urlSchemeTask) {
|
||||
[urlSchemeTask didFinish];
|
||||
}];
|
||||
|
||||
NSNumber *key = [NSNumber numberWithUnsignedLongLong:requestId];
|
||||
[self removeURLSchemeTask:key];
|
||||
}
|
||||
|
||||
- (int) processURLRequestReadBodyStream:(unsigned long long)requestId :(void *)buf :(int)bufLen {
|
||||
int res = 0;
|
||||
int *pRes = &res;
|
||||
|
||||
bool hasRequest = [self processURLSchemeTaskCall:requestId :^(id<WKURLSchemeTask> urlSchemeTask) {
|
||||
NSInputStream *stream = urlSchemeTask.request.HTTPBodyStream;
|
||||
if (!stream) {
|
||||
*pRes = -3;
|
||||
} else {
|
||||
NSStreamStatus status = stream.streamStatus;
|
||||
if (status == NSStreamStatusAtEnd) {
|
||||
*pRes = 0;
|
||||
} else if (status != NSStreamStatusOpen) {
|
||||
*pRes = -4;
|
||||
} else if (!stream.hasBytesAvailable) {
|
||||
*pRes = 0;
|
||||
} else {
|
||||
*pRes = [stream read:buf maxLength:bufLen];
|
||||
}
|
||||
}
|
||||
}];
|
||||
|
||||
if (!hasRequest) {
|
||||
res = -2;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
- (void)webView:(nonnull WKWebView *)webView startURLSchemeTask:(nonnull id<WKURLSchemeTask>)urlSchemeTask {
|
||||
// This callback is run with an autorelease pool
|
||||
const char *url = [urlSchemeTask.request.URL.absoluteString UTF8String];
|
||||
const char *method = [urlSchemeTask.request.HTTPMethod UTF8String];
|
||||
const char *headerJSON = "";
|
||||
const void *body = nil;
|
||||
int bodyLen = 0;
|
||||
int hasBodyStream = 0;
|
||||
|
||||
NSData *headers = [NSJSONSerialization dataWithJSONObject: urlSchemeTask.request.allHTTPHeaderFields options:0 error: nil];
|
||||
if (headers) {
|
||||
NSString* headerString = [[[NSString alloc] initWithData:headers encoding:NSUTF8StringEncoding] autorelease];
|
||||
headerJSON = [headerString UTF8String];
|
||||
}
|
||||
|
||||
if (urlSchemeTask.request.HTTPBody) {
|
||||
body = urlSchemeTask.request.HTTPBody.bytes;
|
||||
bodyLen = urlSchemeTask.request.HTTPBody.length;
|
||||
} else if (urlSchemeTask.request.HTTPBodyStream) {
|
||||
hasBodyStream = 1;
|
||||
[urlSchemeTask.request.HTTPBodyStream open];
|
||||
}
|
||||
|
||||
unsigned long long requestId;
|
||||
@synchronized(self.urlRequests) {
|
||||
self.urlRequestsId++;
|
||||
requestId = self.urlRequestsId;
|
||||
NSNumber *key = [NSNumber numberWithUnsignedLongLong:requestId];
|
||||
self.urlRequests[key] = urlSchemeTask;
|
||||
}
|
||||
|
||||
processURLRequest(self, requestId, url, method, headerJSON, body, bodyLen, hasBodyStream);
|
||||
processURLRequest(self, urlSchemeTask);
|
||||
}
|
||||
|
||||
- (void)webView:(nonnull WKWebView *)webView stopURLSchemeTask:(nonnull id<WKURLSchemeTask>)urlSchemeTask {
|
||||
NSArray<NSNumber*> *keys;
|
||||
@synchronized(self.urlRequests) {
|
||||
keys = [self.urlRequests allKeys];
|
||||
}
|
||||
|
||||
for (NSNumber *key in keys) {
|
||||
if (self.urlRequests[key] == urlSchemeTask) {
|
||||
[self removeURLSchemeTask:key];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void) removeURLSchemeTask:(NSNumber *)urlSchemeTaskKey {
|
||||
id<WKURLSchemeTask> urlSchemeTask = nil;
|
||||
@synchronized(self.urlRequests) {
|
||||
urlSchemeTask = self.urlRequests[urlSchemeTaskKey];
|
||||
}
|
||||
|
||||
if (!urlSchemeTask) {
|
||||
return;
|
||||
}
|
||||
|
||||
NSInputStream *stream = urlSchemeTask.request.HTTPBodyStream;
|
||||
if (stream) {
|
||||
[stream close];
|
||||
}
|
||||
|
||||
@synchronized(self.urlRequests) {
|
||||
[self.urlRequests removeObjectForKey:urlSchemeTaskKey];
|
||||
}
|
||||
}
|
||||
|
||||
- (bool)processURLSchemeTaskCall:(unsigned long long)requestId :(schemeTaskCaller)fn {
|
||||
NSNumber *key = [NSNumber numberWithUnsignedLongLong:requestId];
|
||||
|
||||
id<WKURLSchemeTask> urlSchemeTask;
|
||||
@synchronized(self.urlRequests) {
|
||||
urlSchemeTask = self.urlRequests[key];
|
||||
}
|
||||
|
||||
if (urlSchemeTask == nil) {
|
||||
// Stopped task, drop content...
|
||||
return false;
|
||||
}
|
||||
|
||||
@try {
|
||||
fn(urlSchemeTask);
|
||||
} @catch (NSException *exception) {
|
||||
[self removeURLSchemeTask:key];
|
||||
|
||||
// This is very bad to detect a stopped schemeTask this should be implemented in a better way
|
||||
// But it seems to be very tricky to not deadlock when keeping a lock curing executing fn()
|
||||
// It seems like those call switch the thread back to the main thread and then deadlocks when they reentrant want
|
||||
// to get the lock again to start another request or stop it.
|
||||
if ([exception.reason isEqualToString: @"This task has already been stopped"]) {
|
||||
return false;
|
||||
NSStreamStatus status = stream.streamStatus;
|
||||
if (status != NSStreamStatusClosed && status != NSStreamStatusNotOpen) {
|
||||
[stream close];
|
||||
}
|
||||
|
||||
@throw exception;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation {
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
//go:build darwin
|
||||
|
||||
package darwin
|
||||
|
||||
import (
|
||||
"os/exec"
|
||||
)
|
||||
|
||||
func (f *Frontend) ClipboardGetText() (string, error) {
|
||||
pasteCmd := exec.Command("pbpaste")
|
||||
out, err := pasteCmd.Output()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return string(out), nil
|
||||
}
|
||||
|
||||
func (f *Frontend) ClipboardSetText(text string) error {
|
||||
|
||||
copyCmd := exec.Command("pbcopy")
|
||||
in, err := copyCmd.StdinPipe()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := copyCmd.Start(); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := in.Write([]byte(text)); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := in.Close(); err != nil {
|
||||
return err
|
||||
}
|
||||
return copyCmd.Wait()
|
||||
}
|
||||
@@ -19,13 +19,16 @@ import (
|
||||
"fmt"
|
||||
"html/template"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"unsafe"
|
||||
|
||||
"github.com/wailsapp/wails/v2/pkg/assetserver"
|
||||
"github.com/wailsapp/wails/v2/pkg/assetserver/webview"
|
||||
|
||||
"github.com/wailsapp/wails/v2/internal/binding"
|
||||
"github.com/wailsapp/wails/v2/internal/frontend"
|
||||
"github.com/wailsapp/wails/v2/internal/frontend/assetserver"
|
||||
"github.com/wailsapp/wails/v2/internal/frontend/runtime"
|
||||
"github.com/wailsapp/wails/v2/internal/logger"
|
||||
"github.com/wailsapp/wails/v2/pkg/options"
|
||||
)
|
||||
@@ -33,7 +36,7 @@ import (
|
||||
const startURL = "wails://wails/"
|
||||
|
||||
var messageBuffer = make(chan string, 100)
|
||||
var requestBuffer = make(chan *wkWebViewRequest, 100)
|
||||
var requestBuffer = make(chan webview.Request, 100)
|
||||
var callbackBuffer = make(chan uint, 10)
|
||||
|
||||
type Frontend struct {
|
||||
@@ -86,16 +89,15 @@ func NewFrontend(ctx context.Context, appoptions *options.App, myLogger *logger.
|
||||
} else {
|
||||
appBindings.DB().UpdateObfuscatedCallMap()
|
||||
}
|
||||
assets, err := assetserver.NewAssetServerMainPage(ctx, bindings, appoptions)
|
||||
|
||||
assets, err := assetserver.NewAssetServerMainPage(bindings, appoptions, ctx.Value("assetdir") != nil, myLogger, runtime.RuntimeAssetsBundle)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
assets.ExpectedWebViewHost = result.startURL.Host
|
||||
result.assets = assets
|
||||
|
||||
// Start 10 processors to handle requests in parallel
|
||||
for i := 0; i < 10; i++ {
|
||||
go result.startRequestProcessor()
|
||||
}
|
||||
go result.startRequestProcessor()
|
||||
}
|
||||
|
||||
go result.startMessageProcessor()
|
||||
@@ -111,7 +113,8 @@ func (f *Frontend) startMessageProcessor() {
|
||||
}
|
||||
func (f *Frontend) startRequestProcessor() {
|
||||
for request := range requestBuffer {
|
||||
f.processRequest(request)
|
||||
f.assets.ServeWebViewRequest(request)
|
||||
request.Release()
|
||||
}
|
||||
}
|
||||
func (f *Frontend) startCallbackProcessor() {
|
||||
@@ -341,31 +344,6 @@ func (f *Frontend) ExecJS(js string) {
|
||||
f.mainWindow.ExecJS(js)
|
||||
}
|
||||
|
||||
func (f *Frontend) processRequest(r *wkWebViewRequest) {
|
||||
rw := &wkWebViewResponseWriter{r: r}
|
||||
defer rw.Close()
|
||||
|
||||
f.assets.ProcessHTTPRequest(
|
||||
r.url,
|
||||
rw,
|
||||
func() (*http.Request, error) {
|
||||
req, err := r.GetHttpRequest()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if req.URL.Host != f.startURL.Host {
|
||||
if req.Body != nil {
|
||||
req.Body.Close()
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("Expected host '%s' in request, but was '%s'", f.startURL.Host, req.URL.Host)
|
||||
}
|
||||
return req, nil
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
//func (f *Frontend) processSystemEvent(message string) {
|
||||
// sl := strings.Split(message, ":")
|
||||
// if len(sl) != 2 {
|
||||
@@ -392,3 +370,8 @@ func processMessage(message *C.char) {
|
||||
func processCallback(callbackID uint) {
|
||||
callbackBuffer <- callbackID
|
||||
}
|
||||
|
||||
//export processURLRequest
|
||||
func processURLRequest(ctx unsafe.Pointer, wkURLSchemeTask unsafe.Pointer) {
|
||||
requestBuffer <- webview.NewRequest(wkURLSchemeTask)
|
||||
}
|
||||
|
||||
@@ -219,7 +219,7 @@ int main(int argc, const char * argv[]) {
|
||||
int windowStartState = 0;
|
||||
int startsHidden = 0;
|
||||
WailsContext *result = Create("OI OI!",400,400, frameless, resizable, fullscreen, fullSizeContent, hideTitleBar, titlebarAppearsTransparent, hideTitle, useToolbar, hideToolbarSeparator, webviewIsTransparent, alwaysOnTop, hideWindowOnClose, appearance, windowIsTranslucent, debug, windowStartState,
|
||||
startsHidden, 400, 400, 600, 600);
|
||||
startsHidden, 400, 400, 600, 600, false);
|
||||
SetBackgroundColour(result, 255, 0, 0, 255);
|
||||
void *m = NewMenu("");
|
||||
SetAbout(result, "Fake title", "I am a description", _Users_username_Pictures_SaltBae_png, _Users_username_Pictures_SaltBae_png_len);
|
||||
|
||||
@@ -15,7 +15,7 @@ extern "C"
|
||||
#endif
|
||||
|
||||
void processMessage(const char *);
|
||||
void processURLRequest(void*, unsigned long long, const char *, const char *, const char *, const void *, int, int);
|
||||
void processURLRequest(void *, void*);
|
||||
void processMessageDialogResponse(int);
|
||||
void processOpenFileDialogResponse(const char*);
|
||||
void processSaveFileDialogResponse(const char*);
|
||||
|
||||
@@ -67,6 +67,8 @@ func NewWindow(frontendOptions *options.App, debugMode bool) *Window {
|
||||
|
||||
title = c.String(frontendOptions.Title)
|
||||
|
||||
enableFraudulentWebsiteWarnings := C.bool(frontendOptions.EnableFraudulentWebsiteDetection)
|
||||
|
||||
if frontendOptions.Mac != nil {
|
||||
mac := frontendOptions.Mac
|
||||
if mac.TitleBar != nil {
|
||||
@@ -85,7 +87,7 @@ func NewWindow(frontendOptions *options.App, debugMode bool) *Window {
|
||||
var context *C.WailsContext = C.Create(title, width, height, frameless, resizable, fullscreen, fullSizeContent,
|
||||
hideTitleBar, titlebarAppearsTransparent, hideTitle, useToolbar, hideToolbarSeparator, webviewIsTransparent,
|
||||
alwaysOnTop, hideWindowOnClose, appearance, windowIsTranslucent, debug, windowStartState, startsHidden,
|
||||
minWidth, minHeight, maxWidth, maxHeight)
|
||||
minWidth, minHeight, maxWidth, maxHeight, enableFraudulentWebsiteWarnings)
|
||||
|
||||
// Create menu
|
||||
result := &Window{
|
||||
|
||||
@@ -1,106 +0,0 @@
|
||||
//go:build darwin
|
||||
|
||||
package darwin
|
||||
|
||||
/*
|
||||
#cgo CFLAGS: -x objective-c
|
||||
#cgo LDFLAGS: -framework Foundation -framework Cocoa -framework WebKit
|
||||
|
||||
#import "Application.h"
|
||||
#include <stdlib.h>
|
||||
*/
|
||||
import "C"
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
//export processURLRequest
|
||||
func processURLRequest(ctx unsafe.Pointer, requestId C.ulonglong, url *C.char, method *C.char, headers *C.char, body unsafe.Pointer, bodyLen C.int, hasBodyStream C.int) {
|
||||
var bodyReader io.Reader
|
||||
if body != nil && bodyLen != 0 {
|
||||
bodyReader = bytes.NewReader(C.GoBytes(body, bodyLen))
|
||||
} else if hasBodyStream != 0 {
|
||||
bodyReader = &bodyStreamReader{id: requestId, ctx: ctx}
|
||||
}
|
||||
|
||||
requestBuffer <- &wkWebViewRequest{
|
||||
id: requestId,
|
||||
url: C.GoString(url),
|
||||
method: C.GoString(method),
|
||||
headers: C.GoString(headers),
|
||||
body: bodyReader,
|
||||
ctx: ctx,
|
||||
}
|
||||
}
|
||||
|
||||
type wkWebViewRequest struct {
|
||||
id C.ulonglong
|
||||
url string
|
||||
method string
|
||||
headers string
|
||||
body io.Reader
|
||||
|
||||
ctx unsafe.Pointer
|
||||
}
|
||||
|
||||
func (r *wkWebViewRequest) GetHttpRequest() (*http.Request, error) {
|
||||
req, err := http.NewRequest(r.method, r.url, r.body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if r.headers != "" {
|
||||
var h map[string]string
|
||||
if err := json.Unmarshal([]byte(r.headers), &h); err != nil {
|
||||
return nil, fmt.Errorf("unable to unmarshal request headers: %s", err)
|
||||
}
|
||||
|
||||
for k, v := range h {
|
||||
req.Header.Add(k, v)
|
||||
}
|
||||
}
|
||||
|
||||
return req, nil
|
||||
}
|
||||
|
||||
var _ io.Reader = &bodyStreamReader{}
|
||||
|
||||
type bodyStreamReader struct {
|
||||
id C.ulonglong
|
||||
ctx unsafe.Pointer
|
||||
}
|
||||
|
||||
// Read implements io.Reader
|
||||
func (r *bodyStreamReader) Read(p []byte) (n int, err error) {
|
||||
var content unsafe.Pointer
|
||||
var contentLen int
|
||||
if p != nil {
|
||||
content = unsafe.Pointer(&p[0])
|
||||
contentLen = len(p)
|
||||
}
|
||||
|
||||
res := C.ProcessURLRequestReadBodyStream(r.ctx, r.id, content, C.int(contentLen))
|
||||
if res > 0 {
|
||||
return int(res), nil
|
||||
}
|
||||
|
||||
switch res {
|
||||
case 0:
|
||||
return 0, io.EOF
|
||||
case -1:
|
||||
return 0, fmt.Errorf("body: stream error")
|
||||
case -2:
|
||||
return 0, errRequestStopped
|
||||
case -3:
|
||||
return 0, fmt.Errorf("body: no stream defined")
|
||||
case -4:
|
||||
return 0, io.ErrClosedPipe
|
||||
default:
|
||||
return 0, fmt.Errorf("body: unknown error %d", res)
|
||||
}
|
||||
}
|
||||
@@ -1,81 +0,0 @@
|
||||
//go:build darwin
|
||||
|
||||
package darwin
|
||||
|
||||
/*
|
||||
#cgo CFLAGS: -x objective-c
|
||||
#cgo LDFLAGS: -framework Foundation -framework Cocoa -framework WebKit
|
||||
|
||||
#import "Application.h"
|
||||
#include <stdlib.h>
|
||||
*/
|
||||
import "C"
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"net/http"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
var (
|
||||
errRequestStopped = errors.New("request has been stopped")
|
||||
)
|
||||
|
||||
type wkWebViewResponseWriter struct {
|
||||
r *wkWebViewRequest
|
||||
|
||||
header http.Header
|
||||
wroteHeader bool
|
||||
}
|
||||
|
||||
func (rw *wkWebViewResponseWriter) Header() http.Header {
|
||||
if rw.header == nil {
|
||||
rw.header = http.Header{}
|
||||
}
|
||||
return rw.header
|
||||
}
|
||||
|
||||
func (rw *wkWebViewResponseWriter) Write(buf []byte) (int, error) {
|
||||
rw.WriteHeader(http.StatusOK)
|
||||
|
||||
var content unsafe.Pointer
|
||||
var contentLen int
|
||||
if buf != nil {
|
||||
content = unsafe.Pointer(&buf[0])
|
||||
contentLen = len(buf)
|
||||
}
|
||||
|
||||
if !C.ProcessURLDidReceiveData(rw.r.ctx, rw.r.id, content, C.int(contentLen)) {
|
||||
return 0, errRequestStopped
|
||||
}
|
||||
return contentLen, nil
|
||||
}
|
||||
|
||||
func (rw *wkWebViewResponseWriter) WriteHeader(code int) {
|
||||
if rw.wroteHeader {
|
||||
return
|
||||
}
|
||||
rw.wroteHeader = true
|
||||
|
||||
header := map[string]string{}
|
||||
for k := range rw.Header() {
|
||||
header[k] = rw.Header().Get(k)
|
||||
}
|
||||
headerData, _ := json.Marshal(header)
|
||||
|
||||
var headers unsafe.Pointer
|
||||
var headersLen int
|
||||
if len(headerData) != 0 {
|
||||
headers = unsafe.Pointer(&headerData[0])
|
||||
headersLen = len(headerData)
|
||||
}
|
||||
|
||||
C.ProcessURLDidReceiveResponse(rw.r.ctx, rw.r.id, C.int(code), headers, C.int(headersLen))
|
||||
}
|
||||
|
||||
func (rw *wkWebViewResponseWriter) Close() {
|
||||
if !rw.wroteHeader {
|
||||
rw.WriteHeader(http.StatusNotImplemented)
|
||||
}
|
||||
C.ProcessURLDidFinish(rw.r.ctx, rw.r.id)
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
//go:build linux
|
||||
// +build linux
|
||||
|
||||
package linux
|
||||
|
||||
/*
|
||||
#cgo linux pkg-config: gtk+-3.0 webkit2gtk-4.0
|
||||
|
||||
#include "gtk/gtk.h"
|
||||
#include "webkit2/webkit2.h"
|
||||
|
||||
static gchar* GetClipboardText() {
|
||||
GtkClipboard *clip = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD);
|
||||
return gtk_clipboard_wait_for_text(clip);
|
||||
}
|
||||
|
||||
static void SetClipboardText(gchar* text) {
|
||||
GtkClipboard *clip = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD);
|
||||
gtk_clipboard_set_text(clip, text, -1);
|
||||
|
||||
clip = gtk_clipboard_get(GDK_SELECTION_PRIMARY);
|
||||
gtk_clipboard_set_text(clip, text, -1);
|
||||
}
|
||||
*/
|
||||
import "C"
|
||||
import "sync"
|
||||
|
||||
func (f *Frontend) ClipboardGetText() (string, error) {
|
||||
var text string
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(1)
|
||||
invokeOnMainThread(func() {
|
||||
ctxt := C.GetClipboardText()
|
||||
defer C.g_free(C.gpointer(ctxt))
|
||||
text = C.GoString(ctxt)
|
||||
wg.Done()
|
||||
})
|
||||
wg.Wait()
|
||||
return text, nil
|
||||
}
|
||||
|
||||
func (f *Frontend) ClipboardSetText(text string) error {
|
||||
invokeOnMainThread(func() {
|
||||
ctxt := (*C.gchar)(C.CString(text))
|
||||
defer C.g_free(C.gpointer(ctxt))
|
||||
C.SetClipboardText(ctxt)
|
||||
})
|
||||
return nil
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user